为什么要分析类图?
WMS是一个复杂的模块,就像一个很大的家族,里面有各种角色,认识类图就像是认识WMS模块中的各个角色,不先把人认清楚了,怎么更好的理解他们之间的交互?
我觉得,这也是面向对象的语言魅力,面向对象的语言构建了一个小小的世界,每一个类都是其中的一个角色。
首先插一张类图,方便后面的分析
具体类图小析
ConfigurationContainer
类属性分析
这是WMS模块中的始祖级别的类,WMS中所有的类都继承于它。
ConfigurationContainer类中主要有三个Configuration对象,Configuration 本事就是各种基础参数 mode的记录
mRequestedOverrideConfiguration:当前应用主动请求的Configuration
mResolvedOverrideConfiguration:mRequestedOverrideConfiguration 经过子类的的调整后的对应容器请求的config,子类会重现相关的方法。
mFullConfiguration:当前使用的Configuration。
public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
//下面三个Configuration对象是配置相关的基础对象,onfiguration对象本身主要是一些参数的配置。
/**
* Contains requested override configuration settings applied to this configuration container. 当前应用主动请求的所有config
*/
private Configuration mRequestedOverrideConfiguration = new Configuration();
/**
* Contains the requested override configuration with parent and policy constraints applied.
* This is the set of overrides that gets applied to the full and merged configurations.为mRequestedOverrideConfiguration 经过子类的的调整后的对应容器请求的config
*/
private Configuration mResolvedOverrideConfiguration = new Configuration();
/**
* Contains full configuration applied to this configuration container. Corresponds to full
* parent's config with applied {@link #mResolvedOverrideConfiguration}.为父亲的config(mFullConfiguration) 加上自己的mResolvedOverrideConfiguration 组合成自身的mResolvedOverrideConfiguration
*/
private Configuration mFullConfiguration = new Configuration();//这个是返回的configuration
/**
* Returns full configuration applied to this configuration container.
* This method should be used for getting settings applied in each particular level of the
* hierarchy.从getConfiguration函数中可以看出,mFullConfiguration是在使用的congfiguration
*/
public Configuration getConfiguration() {
return mFullConfiguration;
}
//onConfigurationChanged 当配置发生改变时调用,会在onParentChanged中调用
public void onConfigurationChanged(Configuration newParentConfig) {
mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration); //先保存mResolvedOverrideConfiguration
resolveOverrideConfiguration(newParentConfig);//mResolvedOverrideConfiguration从newParentConfig中算出来
mFullConfiguration.setTo(newParentConfig);//mFullConfiguration 设为 newParentConfig
mFullConfiguration.updateFrom(mResolvedOverrideConfiguration);//重新计算mFullConfiguration
onMergedOverrideConfigurationChanged();
if (!mResolvedTmpConfig.equals(mResolvedOverrideConfiguration)) {
// This depends on the assumption that change-listeners don't do
// their own override resolution. This way, dependent hierarchies
// can stay properly synced-up with a primary hierarchy's constraints.
// Since the hierarchies will be merged, this whole thing will go away
// before the assumption will be broken.
// Inform listeners of the change.
for (int i = mChangeListeners.size() - 1; i >= 0; --i) {
mChangeListeners.get(i).onRequestedOverrideConfigurationChanged(
mResolvedOverrideConfiguration);//通知子节点更新
}
}
for (int i = mChangeListeners.size() - 1; i >= 0; --i) {
mChangeListeners.get(i).onMergedOverrideConfigurationChanged(
mMergedOverrideConfiguration);
}
for (int i = getChildCount() - 1; i >= 0; --i) {
dispatchConfigurationToChild(getChildAt(i), mFullConfiguration);
}
}
//应该是parent发生变化是被调用
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
// Removing parent usually means that we've detached this entity to destroy it or to attach
// to another parent. In both cases we don't need to update the configuration now.
if (newParent != null) {
// Update full configuration of this container and all its children.
onConfigurationChanged(newParent.mFullConfiguration);
// Update merged override configuration of this container and all its children.
onMergedOverrideConfigurationChanged();
}
}
}
WindowContainer
也是一个子孙很多的类(当前WMS模块的类都是其子类),本身也是一个模板类,模板参数是继承于自己的子类。(这种类真的很绕,因为androd framework层面的有很多类树结构的设计,这种设计便于遍历,从而就需要这种模板类)。
类属性分析
持有DisplayContent、SurfaceControl、SurfaceFreezer对象,以及最重要的WindowManagerService对象,这些对象放在这个类,说明这些对象是每一个WMS模块类都需要的。
/**
* Defines common functionality for classes that can hold windows directly or through their 定义了很多公用函数,可以直接用来管理窗口。
* children in a hierarchy form.
* The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
* changes are made to this class.
*/
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable {
/**
* The parent of this window container.
* For removing or setting new parent {@link #setParent} should be used, because it also // 保存父节点
* performs configuration updates based on new parent's settings.
*/
private WindowContainer<WindowContainer> mParent = null;
// List of children for this window container. List is in z-order as the children appear on
// screen with the top-most window container at the tail of the list.
// 存储子节点WindowContainer的list
protected final WindowList<E> mChildren = new WindowList<E>();
// The display this window container is on.
//每一个window 都需要在一个display之上
protected DisplayContent mDisplayContent;
//窗口的内容是绘制在surface上的,SurfaceControl是java层和native层设置surface相关的唯一渠道,所有的surface参数都需要调用SurfaceControl来设置。
protected SurfaceControl mSurfaceControl;
/**
* Windows that clients are waiting to have drawn. 需要等待绘制的窗口List
*/
final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
//动效控制对象
protected final SurfaceAnimator mSurfaceAnimator;
//冻结管理类
final SurfaceFreezer mSurfaceFreezer;
//窗口管理服务对象,WMS的核心管家,虽然不在WMS类图中。就像一个专业的CEO吧,管理大家族公司WindowManagerService值得单独分析
protected final WindowManagerService mWmService;
//留下一个监听用的类
private final List<WindowContainerListener> mListeners = new ArrayList<>();
//配置变换了,要把父节点的配置都改变一下
public void onConfigurationChanged(Configuration newParentConfig) {
super.onConfigurationChanged(newParentConfig);
updateSurfacePositionNonOrganized();
scheduleAnimation();
}
void reparent(WindowContainer newParent, int position) {
...
final WindowContainer oldParent = mParent;
...
// The display object before reparenting as that might lead to old parent getting removed
// from the display if it no longer has any child.
final DisplayContent prevDc = oldParent.getDisplayContent();
final DisplayContent dc = newParent.getDisplayContent();
mReparenting = true;
oldParent.removeChild(this);//将当前window从旧的父节点取下来,放到新的父节点里面
newParent.addChild(this, position);
mReparenting = false;
// Relayout display(s)
dc.setLayoutNeeded();//因为放了新的window过来,则可能需要重新布局
if (prevDc != dc) {
onDisplayChanged(dc);//调用自己的displayChanged函数,对surface做一些处理
prevDc.setLayoutNeeded();//原理的display也需要重新布局
}
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();//暂时不知道功能
// Send onParentChanged notification here is we disabled sending it in setParent for
// reparenting case.
onParentChanged(newParent, oldParent);//调用具体的完成surface相关的细节操作
onSyncReparent(oldParent, newParent);//同步相关的函数
}
/** 重写ConfigureContainer 中的函数
* Update override configuration and recalculate full config.
* @see #mRequestedOverrideConfiguration
* @see #mFullConfiguration
*/
@Override
public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
...
}
/** 主要是调用子节点的onDisplayChanged方法
* Notify that the display this container is on has changed. This could be either this container
* is moved to a new display, or some configurations on the display it is on changes.
*
* @param dc The display this container is on after changes.
*/
void onDisplayChanged(DisplayContent dc) {
if (mDisplayContent != null && mDisplayContent.mChangingContainers.remove(this)) {
// Cancel any change transition queued-up for this container on the old display.
mSurfaceFreezer.unfreeze(getPendingTransaction());
}
mDisplayContent = dc;
if (dc != null && dc != this) {
dc.getPendingTransaction().merge(mPendingTransaction);
}
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer child = mChildren.get(i);
child.onDisplayChanged(dc);
}
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onDisplayChanged(dc);
}
}
//这种forAll的方法都是去遍历子节点,使用callBack函数,开闭原则
void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
forAllWindows(wrapper, traverseTopToBottom);
wrapper.release();
}
boolean forAllActivities(Function<ActivityRecord, Boolean> callback){...};
void forAllTasks(Consumer<Task> callback){};
/** 比较窗口的Z值顺序
* Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
* the input container in terms of z-order.
*/
@Override
public int compareTo(WindowContainer other) {
...规则暂时没有理解,感觉有点意思
}
//动画机制
/**
* Applies the app transition animation according the given the layout properties in the
* window hierarchy.
*
* @param lp The layout parameters of the window. 窗口参数
* @param transit The app transition type indicates what kind of transition to be applied. 过渡动画的类型
* @param enter Whether the app transition is entering transition or not.
* @param isVoiceInteraction Whether the container is participating in voice interaction or not. 这个窗口是否伴有声音交互
* @param sources {@link ActivityRecord}s which causes this app transition animation. 谁发起了这个过渡动画
*
* @return {@code true} when the container applied the app transition, {@code false} if the
* app transition is disabled or skipped.
*
* @see #getAnimationAdapter
*/
boolean applyAnimation(WindowManager.LayoutParams lp, @TransitionOldType int transit,
boolean enter, boolean isVoiceInteraction,
@Nullable ArrayList<WindowContainer> sources) {
...
applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources); //这是关键函数,注意这种Unchecked写法,就是表示这个函数的一些前置条件在调用它的函数中已经分析处理了,它只要安心干活就行,不需要考虑太多前置条件。
}
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,@TransitionOldType int transit, boolean isVoiceInteraction,@Nullable ArrayList<WindowContainer> sources) {
...
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,transit, enter, isVoiceInteraction);//这里用到了适配器设计模式
...
if (adapter != null) {
if (sources != null) {
mSurfaceAnimationSources.addAll(sources);//把suorces添加进来
}
startAnimation(getPendingTransaction(), adapter, !isVisible(),
ANIMATION_TYPE_APP_TRANSITION);//开启动画流程
if (adapter.getShowWallpaper()) {
getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
if (thumbnailAdapter != null) {
mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(),
thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> { });
}
}
}
private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,boolean isVoiceInteraction) {
//从displayInfo中拿一些尺寸数据,当displayInfo出现问题时,动画可能也会出现问题
final DisplayContent displayContent = getDisplayContent();
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
final int width = displayInfo.appWidth;
final int height = displayInfo.appHeight;
//开始做更多的具体行动,为开始动画做准备
final Configuration displayConfig = displayContent.getConfiguration();
final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
}
}
WindowToken
首先理解一下Token这个词,在framework层,token可以简单理解为一种句柄,通过其可以索引到某个对象。比如将Token作为Map的Key。具体到WindowToken,首先它是相关window的句柄,其次它也可以是app的activity的Token.
类属性分析
持有一个IBinder对象 作为实际的token, 因为IBinder类型可以跨进程通信,持有一个Bundle对象,其实传送数据的载体
/**
* Container of a set of related windows in the window manager. Often this is an AppWindowToken,
* which is the handle for an Activity that it uses to display windows. For nested windows, there is
* a WindowToken created for the parent window to manage its children.
*/
//注意WindowToken不是一个模板类,是继承了WindowContainer<WindowState> 这个类,也就是说其继承的WindowContainer中某些模板方法的模板参数已经被具体化成了WindowState
class WindowToken extends WindowContainer<WindowState> {
/** The actual token */
final IBinder token;//只有IBinder类型才能跨进程通信
/**
* Options that will be used to determine which {@link RootDisplayArea} this window should be
* attached to.//Bundle 是传送数据的载体
*/
@Nullable
final Bundle mOptions;
/** 这个内部类看起来是和旋转相关的,后面看动画相关也许要回来看,这里先不过多探究
* Used to fix the transform of the token to be rotated to a rotation different than it's
* display. The window frames and surfaces corresponding to this token will be layouted and
* rotated by the given rotated display info, frames and insets.
*/
private static class FixedRotationTransformState {
final DisplayInfo mDisplayInfo;
final DisplayFrames mDisplayFrames;
final Configuration mRotatedOverrideConfiguration;
final SeamlessRotator mRotator;
/**
* The tokens that share the same transform. Their end time of transform are the same. The
* list should at least contain the token who creates this state.
*/
final ArrayList<WindowToken> mAssociatedTokens = new ArrayList<>(3);
final ArrayList<WindowContainer<?>> mRotatedContainers = new ArrayList<>(3);
final SparseArray<Rect> mBarContentFrames = new SparseArray<>();
boolean mIsTransforming = true;
...
}
}
ActivityRecord
就是表示一个activity,记录了一个activity各种相关参数
final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
final ActivityTaskManagerService mAtmService;
final ActivityInfo info; // activity info provided by developer in AndroidManifest 这个info应该是很原始的信息
// TODO: rename to mActivityToken //这个Token是个内部类
final ActivityRecord.Token appToken;
// the intent component, or target of an alias.一个 intent 组间?
final ComponentName mActivityComponent;
// Input application handle used by the input dispatcher. 输入信息处理者
private InputApplicationHandle mInputApplicationHandle;
final Intent intent; // the original intent that generated us
private Task task; // the task this is in. task是关键
// Last configuration reported to the activity in the client process.
private MergedConfiguration mLastReportedConfiguration;
CompatibilityInfo compat;// last used compatibility mode
ActivityRecord resultTo; // who started this entry, so will get our reply
ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
WindowProcessController app; // if non-null, hosting application
final ActivityTaskSupervisor mTaskSupervisor;
final RootWindowContainer mRootWindowContainer;
/** 在应用旋转场景下提前计算的display大小
* The precomputed display insets for resolving configuration. It will be non-null if
* {@link #shouldCreateCompatDisplayInsets} returns {@code true}.
*/
private CompatDisplayInsets mCompatDisplayInsets;
// Set to the previous Task parent of the ActivityRecord when it is reparented to a new Task 进入画中画前把父节点保存起来
// due to picture-in-picture. This gets cleared whenever this activity or the Task
// it references to gets removed. This should also be cleared when we move out of pip.
private Task mLastParentBeforePip;
DisplayArea
/**
* Container for grouping WindowContainer below DisplayContent.
*
* DisplayAreas are managed by a {@link DisplayAreaPolicy}, and can override configurations and
* can be leashed.
*
* DisplayAreas can contain nested DisplayAreas.
*
* DisplayAreas come in three flavors, to ensure that windows have the right Z-Order:
* - BELOW_TASKS: Can only contain BELOW_TASK DisplayAreas and WindowTokens that go below tasks.
* - ABOVE_TASKS: Can only contain ABOVE_TASK DisplayAreas and WindowTokens that go above tasks.
* - ANY: Can contain any kind of DisplayArea, and any kind of WindowToken or the Task container.
*
* @param <T> type of the children of the DisplayArea.
*/
public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
protected final Type mType;
private final String mName;
final int mFeatureId;
private final DisplayAreaOrganizerController mOrganizerController;
IDisplayAreaOrganizer mOrganizer;
private final Configuration mTmpConfiguration = new Configuration();
/**
* Whether this {@link DisplayArea} should ignore fixed-orientation request. If {@code true}, it
* can never specify orientation, but shows the fixed-orientation apps below it in the
* letterbox; otherwise, it rotates based on the fixed-orientation request.
*/
protected boolean mIgnoreOrientationRequest;
/**
* DisplayArea that contains WindowTokens, and orders them according to their type.
*/
public static class Tokens extends DisplayArea<WindowToken> {
...
}
/**
* DisplayArea that can be dimmed.
*/
static class Dimmable extends DisplayArea<DisplayArea> {
...
}
}
TaskDisplayArea
类属性分析
和surfaceControl关系有一点紧密,持有ActivityTaskManagerService对象。
/**
* {@link DisplayArea} that represents a section of a screen that contains app window containers. 表示包含应用程序窗口容器的屏幕部分
*
* The children can be either {@link Task} or {@link TaskDisplayArea}.
*/
final class TaskDisplayArea extends DisplayArea<WindowContainer> {
DisplayContent mDisplayContent;
/**
* A control placed at the appropriate level for transitions to occur.
*/
private SurfaceControl mAppAnimationLayer;
private SurfaceControl mBoostedAppAnimationLayer;
private SurfaceControl mHomeAppAnimationLayer;
/**
* Given that the split-screen divider does not have an AppWindowToken, it
* will have to live inside of a "NonAppWindowContainer". However, in visual Z order
* it will need to be interleaved with some of our children, appearing on top of
* both docked root tasks but underneath any assistant root tasks.
*
* To solve this problem we have this anchor control, which will always exist so
* we can always assign it the correct value in our {@link #assignChildLayers}.
* Likewise since it always exists, we can always
* assign the divider a layer relative to it. This way we prevent linking lifecycle
* events between tasks and the divider window.
*/
// 看上去 意思是一个分屏线图层
private SurfaceControl mSplitScreenDividerAnchor;
private ActivityTaskManagerService mAtmService;
private RootWindowContainer mRootWindowContainer;
}
Dimmable
static class Dimmable extends DisplayArea<DisplayArea> {
private final Dimmer mDimmer = new Dimmer(this);
private final Rect mTmpDimBoundsRect = new Rect();
}
RootDisplayArea
/**
* Root of a {@link DisplayArea} hierarchy. It can be either the {@link DisplayContent} as the root
* of the whole logical display, or a {@link DisplayAreaGroup} as the root of a partition of the
* logical display.
*/
class RootDisplayArea extends DisplayArea.Dimmable {
/** {@link Feature} that are supported in this {@link DisplayArea} hierarchy. */
List<DisplayAreaPolicyBuilder.Feature> mFeatures;
/**
* Mapping from policy supported {@link Feature} to list of {@link DisplayArea} created to cover
* all the window types that the {@link Feature} will be applied to.
*/
Map<Feature, List<DisplayArea<WindowContainer>>> mFeatureToDisplayAreas;
/** Mapping from window layer to {@link DisplayArea.Tokens} that holds windows on that layer. */
private DisplayArea.Tokens[] mAreaForLayer;
}
DisplayContent
类属性分析
/**
* Utility class for keeping track of the WindowStates and other pertinent contents of a
* particular Display.
*/
class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.DisplayContentInfo {
final ActivityTaskManagerService mAtmService;
/**
* Unique logical identifier of this display.
*
* @see DisplayInfo#displayId
*/
final int mDisplayId;
/**
* Unique physical identifier of this display. Unlike {@link #mDisplayId} this value can change
* at runtime if the underlying physical display changes.
*
* @see DisplayInfo#uniqueId
*/
@Nullable
String mCurrentUniqueDisplayId;
/**
* We organize all top-level Surfaces into the following layer.
* It contains a few Surfaces which are always on top of others, and omitted from
* Screen-Magnification, for example the strict mode flash or the fullscreen magnification
* overlay.
*/
private SurfaceControl mOverlayLayer;
/**
* The direct child layer of the display to put all non-overlay windows. This is also used for
* screen rotation animation so that there is a parent layer to put the animation leash.
*/
private final SurfaceControl mWindowingLayer;
// Contains all IME window containers. Note that the z-ordering of the IME windows will depend
// on the IME target. We mainly have this container grouping so we can keep track of all the IME
// window containers together and move them in-sync if/when needed. We use a subclass of
// WindowContainer which is omitted from screen magnification, as the IME is never magnified.
// TODO(display-area): is "no magnification" in the comment still true?
private final ImeContainer mImeWindowsContainer = new ImeContainer(mWmService);
final AppTransition mAppTransition;
final AppTransitionController mAppTransitionController;
final ArraySet<ActivityRecord> mOpeningApps = new ArraySet<>();
final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>();
final ArraySet<WindowContainer> mChangingContainers = new ArraySet<>();
// Mapping from a token IBinder to a WindowToken object on this display.
private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
DisplayCutout mInitialDisplayCutout; //挖空屏的屏幕信息
RoundedCorners mInitialRoundedCorners; // 圆角信息
/**
* Whether to disable display scaling. This can be set via shell command "adb shell wm scaling".
* @see WindowManagerService#setForcedDisplayScalingMode(int, int)
*/
boolean mDisplayScalingDisabled;
final Display mDisplay;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
private final DisplayPolicy mDisplayPolicy;
private final DisplayRotation mDisplayRotation;
DisplayFrames mDisplayFrames;
WallpaperController mWallpaperController;
private final SurfaceSession mSession = new SurfaceSession();
/**
* Window that is currently interacting with the user. This window is responsible for receiving
* key events and pointer events from the user.
*/
WindowState mCurrentFocus = null;
/**
* The last focused window that we've notified the client that the focus is changed.
*/
WindowState mLastFocus = null;
/**
* The foreground app of this display. Windows below this app cannot be the focused window. If
* the user taps on the area outside of the task of the focused app, we will notify AM about the
* new task the user wants to interact with.
*/
ActivityRecord mFocusedApp = null;
/**
* Container for IME windows.
*
* This has some special behaviors:
* - layers assignment is ignored except if setNeedsLayer() has been called before (and no
* layer has been assigned since), to facilitate assigning the layer from the IME target, or
* fall back if there is no target.
* - the container doesn't always participate in window traversal, according to
* {@link #skipImeWindowsDuringTraversal()}
*/
private static class ImeContainer extends DisplayArea.Tokens {
...
}
}
DisplayAreaGroup
/** The root of a partition of the logical display. */
class DisplayAreaGroup extends RootDisplayArea{
}
Task
class Task extends WindowContainer<WindowContainer> {
Intent intent; // The original intent that started the task. Note that this value can be null.
ComponentName realActivity; // The actual activity component that started the task.
/** The process that had previously hosted the root activity of this task.
* Used to know that we should try harder to keep this process around, in case the
* user wants to return to it. */
private WindowProcessController mRootProcess;
Task mAdjacentTask; // Task adjacent to this one.
int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Task mPrevAffiliate; // previous task in affiliated chain.
int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Task mNextAffiliate; // next task in affiliated chain.
int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
// For relaunching the task from recents as though it was launched by the original launcher.
int mCallingUid;
String mCallingPackage;
String mCallingFeatureId;
// Minimal width and height of this task when it's resizeable. -1 means it should use the
// default minimal width/height.
int mMinWidth;
int mMinHeight;
// The surface transition of the target when recents animation is finished.
// This is originally introduced to carry out the current surface control position and window
// crop when a multi-activity task enters pip with autoEnterPip enabled. In such case,
// the surface control of the task will be animated in Launcher and then the top activity is
// reparented to pinned root task.
// Do not forget to reset this after reparenting.
// TODO: remove this once the recents animation is moved to the Shell
PictureInPictureSurfaceTransaction mLastRecentsAnimationTransaction;
// The content overlay to be applied with mLastRecentsAnimationTransaction
// TODO: remove this once the recents animation is moved to the Shell
SurfaceControl mLastRecentsAnimationOverlay;
final ActivityTaskManagerService mAtmService;
final ActivityTaskSupervisor mTaskSupervisor;
final RootWindowContainer mRootWindowContainer;
/* Unique identifier for this task. */
final int mTaskId;
/* User for which this task was created. */
// TODO: Make final
int mUserId;
/**
* Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
* moved to a new display.
*/
@Surface.Rotation
private int mRotation;
private Dimmer mDimmer = new Dimmer(this);
private final Rect mTmpDimBoundsRect = new Rect();
/** ActivityRecords that are exiting, but still on screen for animations. */
final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
// When non-null, this is a transaction that will get applied on the next frame returned after
// a relayout is requested from the client. While this is only valid on a leaf task; since the
// transaction can effect an ancestor task, this also needs to keep track of the ancestor task
// that this transaction manipulates because deferUntilFrame acts on individual surfaces.
SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
Task mMainWindowSizeChangeTask;
}
RootWindowContainer
class RootWindowContainer extends WindowContainer<DisplayContent>
implements DisplayManager.DisplayListener {
private Object mLastWindowFreezeSource = null;
private Session mHoldScreen = null;
// Following variables are for debugging screen wakelock only.
// Last window that requires screen wakelock
WindowState mHoldScreenWindow = null;
// Last window that obscures all windows below
WindowState mObscuringWindow = null;
private final Handler mHandler;
// The ID of the display which is responsible for receiving display-unspecified key and pointer
// events.
private int mTopFocusedDisplayId = INVALID_DISPLAY;
// Map from the PID to the top most app which has a focused window of the process.
final ArrayMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new ArrayMap<>();
// Only a separate transaction until we separate the apply surface changes
// transaction from the global transaction.
private final SurfaceControl.Transaction mDisplayTransaction;
ActivityTaskManagerService mService;
ActivityTaskSupervisor mTaskSupervisor;
WindowManagerService mWindowManager;
DisplayManager mDisplayManager;
private DisplayManagerInternal mDisplayManagerInternal;
/** Reference to default display so we can quickly look it up. */
private DisplayContent mDefaultDisplay;
}
WindowState
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
InsetsControlTarget {
final WindowManagerPolicy mPolicy;
final Context mContext;
final Session mSession;
final IWindow mClient;
WindowToken mToken;
ActivityRecord mActivityRecord;
final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
final DeathRecipient mDeathRecipient;
private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
/** @see #addEmbeddedDisplayContent(DisplayContent dc) */
private final ArraySet<DisplayContent> mEmbeddedDisplayContents = new ArraySet<>();
/**
* Used to store last reported to client configuration and check if we have newer available.
* We'll send configuration to client only if it is different from the last applied one and
* client won't perform unnecessary updates.
*/
private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration();
private final Configuration mTempConfiguration = new Configuration();
/**
* These are the content insets that were given during layout for
* this window, to be applied to windows behind it.
*/
final Rect mGivenContentInsets = new Rect();
/**
* These are the visible insets that were given during layout for
* this window, to be applied to windows behind it.
*/
final Rect mGivenVisibleInsets = new Rect();
/**
* This is the given touchable area relative to the window frame, or null if none.
*/
final Region mGivenTouchableRegion = new Region();
private final WindowFrames mWindowFrames = new WindowFrames();
private final ClientWindowFrames mClientWindowFrames = new ClientWindowFrames();
/** The frames used to compute a temporal layout appearance. */
private WindowFrames mSimulatedWindowFrames;
/**
* List of rects where system gestures should be ignored.
*
* Coordinates are relative to the window's position.
*/
private final List<Rect> mExclusionRects = new ArrayList<>();
// Input channel and input window handle used by the input dispatcher.
final InputWindowHandleWrapper mInputWindowHandle;
InputChannel mInputChannel;
final WindowStateAnimator mWinAnimator;
// If not null, the window that will be used to replace the old one. This is being set when
// the window is added and unset when this window reports its first draw.
private WindowState mReplacementWindow = null;
private final Transaction mTmpTransaction;
/**
* The insets state of sources provided by windows above the current window.
*/
final InsetsState mAboveInsetsState = new InsetsState();
/**
* The insets sources provided by this window.
*/
final SparseArray<InsetsSource> mProvidedInsetsSources = new SparseArray<>();
/**
* A region inside of this window to be excluded from touch.
*/
private final Region mTapExcludeRegion = new Region();
/**
* Used for testing because the real PowerManager is final.
*/
private PowerManagerWrapper mPowerManagerWrapper;
/**
* Indicates whether we have requested a Dim (in the sense of {@link Dimmer}) from our host
* container.
*/
private boolean mIsDimming = false;
private @Nullable InsetsSourceProvider mControllableInsetProvider;
private final InsetsState mRequestedInsetsState = new InsetsState();
/**
* Freeze the insets state in some cases that not necessarily keeps up-to-date to the client.
* (e.g app exiting transition)
*/
private InsetsState mFrozenInsetsState;
}
就这样,先大致过一遍各个类及属性,后面分析一些关键流程的时候再仔细看。