WMS类图分析-android12

news2024/12/27 12:19:36

为什么要分析类图?

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;
        }

就这样,先大致过一遍各个类及属性,后面分析一些关键流程的时候再仔细看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/111440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue+antd搭建后台管理界面模版(PC端),适配中文、英文、日文 mock数据,开箱即用

vueantd搭建后台管理界面模版&#xff08;PC端&#xff09; 完整代码下载地址&#xff1a;vueantd搭建后台管理界面模版&#xff08;PC端&#xff09; 技术栈 vue2 vuex vue-router webpack ES6/7 axios antd 阿里图标iconfont 项目预览 http://nmgwap.gitee.io/vue…

【软件工程】实验4:校园二手物品交易过程的UI设计

文章目录校园二手物品交易过程的UI设计通过“用户画像”对用户群体进行分析校园二手物品交易过程UI设计&#xff08;Figma&#xff09;校园二手物品交易过程的UI设计 通过“用户画像”对用户群体进行分析 大学校园交易市场特点&#xff1a; 容量大。随着我国高等教育近年来的连…

Kubernetes部署_使用kubernetes部署Mysql主从结构(Kubernetes工作实践类)

文章目录一、前言二、实际操作步骤1&#xff1a;编写namespace脚本步骤2&#xff1a;编写configmap脚本步骤3&#xff1a;编写secret脚本(用来存放mysql密码)步骤4&#xff1a;编写initContainer脚本步骤5&#xff1a;编写StorageClass相关脚本1&#xff09;权限设置&#xff1…

干货分享 | To B业务的用户运营五要点

随着产业互联网格局的逐渐深化&#xff0c;近年来&#xff0c;To B业务逐渐被互联网改变和赋能。为了更高效地获客和服务&#xff0c;更多的运营手段逐渐被运用在To B业务之中&#xff0c;而To B运营也变得越来越重要。 作为一家To B企业&#xff0c;AdBright常常收到网友的提问…

YOLOV3论文学习

YOLOv3论文链接&#xff1a;https://pjreddie.com/media/files/papers/YOLOv3.pdf 综述 一、摘要 1、320*320的YOLOv3推理时间22ms&#xff0c;准确率28.2mAP&#xff0c;达到了SSD的精确度&#xff0c;推理速度却快了三倍。 2、基于.5mAp Iou 的YOLOv3的检测效果还比较不错&a…

Python使用Pandas导入数据库sql

Python使用Pandas导入数据库sql一、前言二、准备工作三、从数据库导入数据到Pandas一、前言 对于关系数据库的访问&#xff0c;Python社区已经制定出一个标准&#xff0c;称为Python Database API Specification。Mysql&#xff0c;Oracal等特定数据库模块都遵从这一规范&…

QT 学习笔记(十一)

文章目录一、绘图设备1. QPixmap1.1 QPixmap 简介1.2 QPixmap 演示2. QBitmap2.1 QBitmap 简介2.2 QBitmap 演示见 QPixmap 和 QBitmap 的区别。3. QImage3.1 QImage 简介3.2 QImage 演示4. QPicture4.1 QPicture 简介4.2 QPicture 演示二、QPixmap 和 QBitmap 的区别1. widget…

Python正在消亡?致命弱点是否会让Python被新语言取代?

被业界称为“瑞士军刀”的编程语言&#xff0c;可能会被更适合该任务的其他语言取代吗&#xff1f; 自从1990年代初Python发布以来&#xff0c;它引起了很多热议。当然&#xff0c;编程社区花了至少20年的时间才逐渐注意到它的存在&#xff0c;而当它一旦开始流行起来&#xf…

Web入门开发【一】- Web开发介绍

欢迎来到霍大侠的小院&#xff0c;我们来学习Web入门开发的系列课程。 首先我们来了解下这个课程能学到什么&#xff1f; 1、你将可以掌握Web网站的开发全过程。 2、了解基础的HTML&#xff0c;CSS&#xff0c;JavaScript语言。 3、开发自己的第一个网站。 4、认识很多对编…

UML类关系

1、聚合关系&#xff08;aggregation&#xff09; 用空心菱形箭头表示&#xff0c;整体和部分有各自的生命周期。部分可以属于多个整体对象! class Student; class Class { private: Student s; public: void set_student(Student s) { this.s s; } }; student() { print(“c…

电脑商城网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 作为一个网上商城系统&#xff0c;就应该做到能提供强大的业务支持功能&#xff0c;系统能实现用户的注册功能、登录 功…

整理各种Vue项目在IE浏览器白屏报错 SCRIPT1002:语法错误

目录 一、关于 sockjs-client 依赖包 二、关于 highlight 依赖包 三、关于 swiper 依赖包 四、IE 不支持 ES6 语法 五、第三方插件引入导致 六、本地环境正常&#xff0c;生产环境仍旧白屏 这篇文章主要介绍了 Vue 项目在 IE 浏览器显示白屏并报错 SCRIPT1002: 语法错误 …

【数字信号处理】卷积和乘法系列3之傅里叶变换对III

“傅里叶”家族 引言 虽然你知道傅里叶级数和变换,但看看它们之间的关系是很有趣的。本节的目的是展示各种基于傅立叶的变换如何相互关联。 要做到这一点,有必要认识到存在一个具有四个成员的傅里叶“家族”,如图 30 所示。有四个是因为除了具有系列与变换选项(行)外,…

转行的35岁程序员们

“大龄程序员去哪儿了”&#xff0c;10月24日程序员节当天&#xff0c;这成为了社交媒体上最火的话题之一。根据澎湃新闻统计&#xff0c;在知乎、豆瓣上关于“大龄程序员”的369个有效提问里&#xff0c;大龄程序员的职场成长问题最受关注&#xff0c;一共有242个&#xff0c;…

给刚入职场的年轻人八条建议

年轻人刚入职场时&#xff0c;总会碰到各种各样的难题&#xff0c;作为过来人&#xff0c;很多新人的难处我也深有体会。想要快速融入职场是没有捷径的&#xff0c;但是如果处理得当&#xff0c;还是可以少走很多弯路&#xff0c;以下就是我总结的给刚入职场的年轻人的八条建议…

JavaDS1-时间复杂度空间复杂度

目录 1.算法效率 1.1.时间效率&#xff08;时间复杂度&#xff09;——衡量算法运行速度 1.2.空间效率&#xff08;空间复杂度&#xff09;——衡量算法所需额外空间&#xff08;如今不再特别关注&#xff09; 2.时间复杂度 2.1.概念 2.2.大O的渐进表示法 2.2.1.O(F(n))…

【约数】魔法数

K-魔法数_2022河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;郑州大学 (nowcoder.com) 题意&#xff1a; 思路&#xff1a; 一开始想的是枚举到1e6&#xff0c;统计所有数的约数个数&#xff0c;然后就不知道然后了&#xff0c;甚至想放到同一个数组里面然后lower_…

遇事不决,转行做程序员?先看看转了的人怎么说

遇事不决先“转码”——近几年&#xff0c;这好像成了非程序员考虑转行方向的优先选择。 转码&#xff0c;指放弃原职业或专业&#xff0c;转行成为程序员。通过“转码”这一跳板&#xff0c;有人在互联网行业谋得一份薪水更高的工作&#xff0c;还有人借此申请出国读书工作、…

大龄转行当程序员怎么做?应该选择小众技术,避免与年轻人竞争?

最近&#xff0c;一篇关于一位大龄人士转行&#xff0c;成为程序员的文章引起了关于 HN 的热议。文章作者 Derek M. Jones 是一名从事该行业十多年的软件工程师。最近&#xff0c;他遇到了许多想要转行到软件开发方面的年长求职者。对此&#xff0c;他的建议是&#xff1a;选择…

【源码共读】yocto-queue 一个微型队列数据结构

yocto-queue是一个微型队列的数据结构&#xff0c;根据作者的介绍&#xff0c;如果在你一个数据量很大的数组上&#xff0c;大量的操作Array.push和Array.shift&#xff0c;那么你可以考虑使用yocto-queue来替代Array。 因为Array.shift的时间复杂度是O(n)&#xff0c;而Queue…