wms add window 流程

news2024/12/29 11:25:38

 ======================

二、WMS 窗口添加流程

/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java

    boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
            boolean andResume, boolean checkConfig) throws RemoteException {

.....
// 打印log restarrt activty
                EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),
                        task.mTaskId, r.shortComponentName);

。。。。。

// 1-1)创建 ClientTransaction 对象 ClientTransaction.obtain
                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.appToken);

                final boolean isTransitionForward = r.isTransitionForward();

// 1-2) ClientTransaction增加 回调为 LaunchActivityItem
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                        r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
                        r.takeOptions(), isTransitionForward,
                        proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
                        r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
                        r.getLaunchedFromBubble()));

                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;

// 1-3)如果 resume 则 创建 ResumeActivityItem 对象
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
// 1-4)ClientTransaction 设置 生命周期请求
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.
// 1-5)安排 transaction
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);

// 1-1)创建 ClientTransaction 对象 ClientTransaction.obtain

 /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

    public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
        ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);
        if (instance == null) {
            instance = new ClientTransaction();
        }

// client 为客户客户端主线程为:ActivityThread
        instance.mClient = client;
// activty 的 Token
        instance.mActivityToken = activityToken;
// 返回 ClientTransaction 对象
        return instance;
    }

// 1-2) ClientTransaction增加 回调为 LaunchActivityItem
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),

/frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java

LaunchActivityItem.obtain 方法

    public static LaunchActivityItem obtain(Intent intent, int ident, ActivityInfo info,
            Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo,
            String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state,
            PersistableBundle persistentState, List<ResultInfo> pendingResults,
            List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
            boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
            IActivityClientController activityClientController,
            FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken,
            boolean launchedFromBubble) {

// 获取到 LaunchActivityItem 对象
        LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
        if (instance == null) {
            instance = new LaunchActivityItem();
        }

// 设置 LaunchActivityItem 的一些参数
        setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
                voiceInteractor, procState, state, persistentState, pendingResults,
                pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
                activityClientController, fixedRotationAdjustments, shareableActivityToken,
                launchedFromBubble);

        return instance;
    }

clientTransaction.addCallback 增加 callback 为 LaunchActivityItem

    public void addCallback(ClientTransactionItem activityCallback) {
        if (mActivityCallbacks == null) {
            mActivityCallbacks = new ArrayList<>();
        }

// 将 LaunchActivityItem 保存到 mActivityCallbacks 中
        mActivityCallbacks.add(activityCallback);
    }

// 1-3)如果 resume 则 创建 ResumeActivityItem 对象
                    lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);

/frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java

    public static ResumeActivityItem obtain(boolean isForward) {
        ResumeActivityItem instance = ObjectPool.obtain(ResumeActivityItem.class);
        if (instance == null) {
            instance = new ResumeActivityItem();
        }
        instance.mProcState = ActivityManager.PROCESS_STATE_UNKNOWN;
        instance.mUpdateProcState = false;
        instance.mIsForward = isForward;

// 创建 ResumeActivityItem 对象
        return instance;
    }


// 1-4)ClientTransaction 设置 生命周期请求
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

设置客户端在执行事务后的事务

    public void setLifecycleStateRequest(ActivityLifecycleItem stateRequest) {
        mLifecycleStateRequest = stateRequest;
    }

// 1-5)安排 transaction
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);

/frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java

    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();

// ClientTransaction 去调度
        transaction.schedule();
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }
    }

/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

    /** Target client. */
    private IApplicationThread mClient;

    public void schedule() throws RemoteException {
/// 用户进程处理
        mClient.scheduleTransaction(this);
    }

/frameworks/base/core/java/android/app/ActivityThread.java

// ActivityThread  继承了 ClientTransactionHandler
public final class ActivityThread extends ClientTransactionHandler
        implements ActivityThreadInternal {

    private class ApplicationThread extends IApplicationThread.Stub {

        @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
// 父类ClientTransactionHandler 执行 scheduleTransaction
            ActivityThread.this.scheduleTransaction(transaction);
        }

// 父类ClientTransactionHandler 执行 scheduleTransaction

/frameworks/base/core/java/android/app/ClientTransactionHandler.java

public abstract class ClientTransactionHandler {

    // Schedule phase related logic and handlers.

    /** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {

// 先预处理该事务
        transaction.preExecute(this);
// 然后再发送消息 EXECUTE_TRANSACTION
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }

先预处理该事务     transaction.preExecute

/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

    public void preExecute(android.app.ClientTransactionHandler clientTransactionHandler) {
        if (mActivityCallbacks != null) {
            final int size = mActivityCallbacks.size();
            for (int i = 0; i < size; ++i) {

// clientTransactionHandler 为 activitythread,LaunchActivityItem预处理
                mActivityCallbacks.get(i).preExecute(clientTransactionHandler, mActivityToken);
            }
        }
        if (mLifecycleStateRequest != null) {
// 然后ResumeActivityItem 预处理事务
            mLifecycleStateRequest.preExecute(clientTransactionHandler, mActivityToken);
        }
    }

// clientTransactionHandler 为 activitythread,LaunchActivityItem预处理

/frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java

    @Override
    public void preExecute(ClientTransactionHandler client, IBinder token) {
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
                client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken,
                mLaunchedFromBubble);

// 将对应的activity 事件保存到 mLaunchingActivities 中
        client.addLaunchingActivity(token, r);
        client.updateProcessState(mProcState, false);
        client.updatePendingConfiguration(mCurConfig);
        if (mActivityClientController != null) {
            ActivityClient.setActivityClientController(mActivityClientController);
        }
    }

// 然后ResumeActivityItem 预处理事务

// 再发送消息 EXECUTE_TRANSACTION在主线程执行
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction)

/frameworks/base/core/java/android/app/ActivityThread.java

    // An executor that performs multi-step transactions.
    private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {

                case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
// TransactionExecutor 去执行处理
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        // Client transactions inside system process are recycled on the client side
                        // instead of ClientLifecycleManager to avoid being cleared before this
                        // message is handled.
                        transaction.recycle();
                    }
                    // TODO(lifecycler): Recycle locally scheduled transactions.
                    break;

/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

    /** Initialize an instance with transaction handler, that will execute all requested actions. */
    public TransactionExecutor(ClientTransactionHandler clientTransactionHandler) {
        mTransactionHandler = clientTransactionHandler;
    }

    /**
     * Resolve transaction.
     * First all callbacks will be executed in the order they appear in the list. If a callback
     * requires a certain pre- or post-execution state, the client will be transitioned accordingly.
     * Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
     * either remain in the initial state, or last state needed by a callback.
     */
    public void execute(ClientTransaction transaction) {
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");

        final IBinder token = transaction.getActivityToken();
        if (token != null) {
            final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
                    mTransactionHandler.getActivitiesToBeDestroyed();
            final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
            if (destroyItem != null) {
                if (transaction.getLifecycleStateRequest() == destroyItem) {
                    // It is going to execute the transaction that will destroy activity with the
                    // token, so the corresponding to-be-destroyed record can be removed.
                    activitiesToBeDestroyed.remove(token);
                }
                if (mTransactionHandler.getActivityClient(token) == null) {
                    // The activity has not been created but has been requested to destroy, so all
                    // transactions for the token are just like being cancelled.
                    Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n"
                            + transactionToString(transaction, mTransactionHandler));
                    return;
                }
            }
        }

        if (DEBUG_RESOLVER) Slog.d(TAG, transactionToString(transaction, mTransactionHandler));

// 1-5-1)执行回调 executeCallbacks
        executeCallbacks(transaction);

// 1-5-2)执行事务生命周期 executeLifecycleState
        executeLifecycleState(transaction);
        mPendingActions.clear();
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
    }

// 1-5-1)循环遍历回调请求的所有状态,并在适当的时间执行它们。执行回调 executeCallbacks

    public void executeCallbacks(ClientTransaction transaction) {

// 获取到 callbacks 为:LaunchActivityItem.java
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
        if (callbacks == null || callbacks.isEmpty()) {
            // No callbacks to execute, return early.
            return;
        }
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callbacks in transaction");

        final IBinder token = transaction.getActivityToken();
        ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

        // In case when post-execution state of the last callback matches the final state requested
        // for the activity in this transaction, we won't do the last transition here and do it when
        // moving to final state instead (because it may contain additional parameters from server).

// 获取到下一个事务,为:ResumeActivityItem.java
        final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();

// ResumeActivityItem获取到的状态 getTargetState为:ON_RESUME
        final int finalState = finalStateRequest != null ? finalStateRequest.getTargetState()
                : UNDEFINED;
        // Index of the last callback that requests some post-execution state.
        final int lastCallbackRequestingState = lastCallbackRequestingState(transaction);

        final int size = callbacks.size();

// 遍历所有的callbacks
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
            if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);

// post 的值为 UNDEFINED
            final int postExecutionState = item.getPostExecutionState();
            final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                    item.getPostExecutionState());

// closestPreExecutionState  也是 UNDEFINED
            if (closestPreExecutionState != UNDEFINED) {
                cycleToPath(r, closestPreExecutionState, transaction);
            }

// 执行 LaunchActivityItem 的execute 和 postExecute
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
            if (r == null) {
                // Launch activity request will create an activity record.
                r = mTransactionHandler.getActivityClient(token);
            }

            if (postExecutionState != UNDEFINED && r != null) {
                // Skip the very last transition and perform it by explicit state request instead.
                final boolean shouldExcludeLastTransition =
                        i == lastCallbackRequestingState && finalState == postExecutionState;
                cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
            }
        }
    }

// 执行 LaunchActivityItem 的execute 和 postExecute

/frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java

打印的trace  activityStart 是执行 oncreate 周期

    @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {

// 会打印对应的 trace:activityStart
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = client.getLaunchingActivity(token);

// 调用 ActivityThread 的 handleLaunchActivity 函数
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

// post 就调用 ActivityThread 移除了这个acvity token
    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        client.removeLaunchingActivity(token);
    }

// 调用 ActivityThread 的 handleLaunchActivity 函数

/frameworks/base/core/java/android/app/ActivityThread.java

    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        if (r.mPendingFixedRotationAdjustments != null) {
            // The rotation adjustments must be applied before handling configuration, so process
            // level display metrics can be adjusted.
            overrideApplicationDisplayAdjustments(r.token, adjustments ->
                    adjustments.setFixedRotationAdjustments(r.mPendingFixedRotationAdjustments));
        }

        // Make sure we are running with the most recent config.
        mConfigurationController.handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        if (ThreadedRenderer.sRendererEnabled
                && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
            HardwareRenderer.preload();
        }

// 初始化,保证获取到 WMS,跨进程通信
        WindowManagerGlobal.initialize();

        // Hint the GraphicsEnvironment that an activity is launching on the process.
        GraphicsEnvironment.hintActivityLaunch();

// 去启动这个 activity:performLaunchActivity
        final Activity a = performLaunchActivity(r, customIntent);

// activity 是不为null 的
        if (a != null) {
            r.createdConfig = new Configuration(mConfigurationController.getConfiguration());
            reportSizeConfigurations(r);
            if (!r.activity.mFinished && pendingActions != null) {

// 去设置  pendingActions 的一些状态
                pendingActions.setOldState(r.state);
                pendingActions.setRestoreInstanceState(true);
                pendingActions.setCallOnPostCreate(true);
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED,
                    null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        }

        return a;
    }

// 去启动这个 activity:performLaunchActivity

    /**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
。。。
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
// 反射去创建这个 activity
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);


        try {
// 创建 Application 对象
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
。。。
                appContext.setOuterContext(activity);

// 执行 activity 的attach 方法
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken, r.shareableActivityToken);
。。。
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
// callActivityOnCreate回调 oncreate 方法
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }

/ 设置生命周期为 ON_CREATE
            r.setState(ON_CREATE);

 callActivityOnCreate回调 oncreate 方法 ,会在 activity 的 performcreate 方法中,打印对应的trace。

// 执行 activity 的attach 方法

/frameworks/base/core/java/android/app/Activity.java

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
            IBinder shareableActivityToken) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

// 创建 PhoneWindow 对象
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(mWindowControllerCallback);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
// 缓存 ui 线程
        mUiThread = Thread.currentThread();
// 设置主线程
        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mAssistToken = assistToken;
        mShareableActivityToken = shareableActivityToken;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

// PhoneWindow 设置 WindowManager:setWindowManager
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }

// 缓存PhoneWindow获取到的 的WindowManager,就是 setWindowManager 的
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);
        mWindow.setPreferMinimalPostProcessing(
                (info.flags & ActivityInfo.FLAG_PREFER_MINIMAL_POST_PROCESSING) != 0);

        setAutofillOptions(application.getAutofillOptions());
        setContentCaptureOptions(application.getContentCaptureOptions());
    }

=======
// mWindowManager 可以通过下列接口去获取,在activityThread 获取到
    public WindowManager getWindowManager() {
        return mWindowManager;
    }

// PhoneWindow 设置 WindowManager:setWindowManager

 /frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java

// PhoneWindow  继承了 Window
public class PhoneWindow extends Window implements MenuBuilder.Callback {

    private final static String TAG = "PhoneWindow";

在父类中设置

/frameworks/base/core/java/android/view/Window.java

    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        mAppToken = appToken;
        mAppName = appName;
// 缓存是否硬件加速
        mHardwareAccelerated = hardwareAccelerated;
        if (wm == null) {
            wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        }
// 创建 mWindowManager :createLocalWindowManager
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
    }

========
// 获取到 mWindowManager 

    public WindowManager getWindowManager() {
        return mWindowManager;
    }

// 创建 mWindowManager :createLocalWindowManager

parentWindow 为 PhoneWindow

mGlobal 是 WindowManagerGlobal

/frameworks/base/core/java/android/view/WindowManagerImpl.java

public final class WindowManagerImpl implements WindowManager {
    @UnsupportedAppUsage
    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {

// parentWindow 为 PhoneWindow
// 创建 WindowManagerImpl 对象
        return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken);
    }

所以:activity.getWindowManager 是 WindowManagerImpl.在:handleResumeActivity会调用

// 1-5-2)执行事务生命周期 executeLifecycleState

/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

    /** Transition to the final state if requested by the transaction. */
    private void executeLifecycleState(ClientTransaction transaction) {

// 获取到  ResumeActivityItem.java
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        if (lifecycleItem == null) {
            // No lifecycle request, return early.
            return;
        }

        final IBinder token = transaction.getActivityToken();
        final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
        if (DEBUG_RESOLVER) {
            Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
                    + lifecycleItem + " for activity: "
                    + getShortActivityName(token, mTransactionHandler));
        }

        if (r == null) {
            // Ignore requests for non-existent client records for now.
            return;
        }

// 1-5-2-1)去循环cycleToPath执行到 on_resume
        // Cycle to the state right before the final requested state.
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);

        // Execute the final transition with proper parameters.

// 1-5-2-2)然后执行 ResumeActivityItem的 execute 和 postExecute
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }

//  1-5-2-1)去循环cycleToPath执行到 on_resume,传入 excludeLastState 值为 true

    private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
            ClientTransaction transaction) {

// start 的值是 on_create,finish 是on_resume
        final int start = r.getLifecycleState();
        if (DEBUG_RESOLVER) {
            Slog.d(TAG, tId(transaction) + "Cycle activity: "
                    + getShortActivityName(r.token, mTransactionHandler)
                    + " from: " + getStateName(start) + " to: " + getStateName(finish)
                    + " excludeLastState: " + excludeLastState);
        }
// 获取到path
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
// 接下来执行 performLifecycleSequence
        performLifecycleSequence(r, path, transaction);
    }

/frameworks/base/core/java/android/app/servertransaction/TransactionExecutorHelper.java

///  该helper 类是真正去找到下一个生命周期的值

    @VisibleForTesting
    public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
        if (start == UNDEFINED || finish == UNDEFINED) {
            throw new IllegalArgumentException("Can't resolve lifecycle path for undefined state");
        }
        if (start == ON_RESTART || finish == ON_RESTART) {
            throw new IllegalArgumentException(
                    "Can't start or finish in intermittent RESTART state");
        }
        if (finish == PRE_ON_CREATE && start != finish) {
            throw new IllegalArgumentException("Can only start in pre-onCreate state");
        }

        mLifecycleSequence.clear();
        if (finish >= start) {
            if (start == ON_START && finish == ON_STOP) {
                // A case when we from start to stop state soon, we don't need to go
                // through the resumed, paused state.
                mLifecycleSequence.add(ON_STOP);
            } else {
                // just go there
// start 为 on_create, finish是 on_resume
                for (int i = start + 1; i <= finish; i++) {
// 将 on_start, on_reusme 增加到 mLifecycleSequence 中
                    mLifecycleSequence.add(i);
                }
            }
        } else { // finish < start, can't just cycle down
            if (start == ON_PAUSE && finish == ON_RESUME) {
                // Special case when we can just directly go to resumed state.
                mLifecycleSequence.add(ON_RESUME);
            } else if (start <= ON_STOP && finish >= ON_START) {
                // Restart and go to required state.

                // Go to stopped state first.
                for (int i = start + 1; i <= ON_STOP; i++) {
                    mLifecycleSequence.add(i);
                }
                // Restart
                mLifecycleSequence.add(ON_RESTART);
                // Go to required state
                for (int i = ON_START; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            } else {
                // Relaunch and go to required state

                // Go to destroyed state first.
                for (int i = start + 1; i <= ON_DESTROY; i++) {
                    mLifecycleSequence.add(i);
                }
                // Go to required state
                for (int i = ON_CREATE; i <= finish; i++) {
                    mLifecycleSequence.add(i);
                }
            }
        }

        // Remove last transition in case we want to perform it with some specific params.
// excludeLastState  移除最后一个值,为on_reums,所以只有on-start
        if (excludeLastState && mLifecycleSequence.size() != 0) {
            mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
        }

        return mLifecycleSequence;
    }

// 接下来执行 performLifecycleSequence

    /** Transition the client through previously initialized state sequence. */
    private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
            ClientTransaction transaction) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            if (DEBUG_RESOLVER) {
                Slog.d(TAG, tId(transaction) + "Transitioning activity: "
                        + getShortActivityName(r.token, mTransactionHandler)
                        + " to state: " + getStateName(state));
            }
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;

// 只有 on-start ,activitythread执行  handleStartActivity
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, mPendingActions,
                            null /* activityOptions */);
                    break;
                case ON_RESUME:

                case ON_PAUSE:

                case ON_STOP:

                case ON_DESTROY:
。。
                    break;
                case ON_RESTART:

                default:
                    throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
            }
        }
    }

执行 onstart :handleStartActivity

/frameworks/base/core/java/android/app/ActivityThread.java

    @Override
    public void handleStartActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, ActivityOptions activityOptions) {
        final Activity activity = r.activity;


        // Start
// 回调 activity 的 onstart
        activity.performStart("handleStartActivity");
// 设置状态为 ON_START
        r.setState(ON_START);

        if (pendingActions == null) {
            // No more work to do.
            return;
        }

// 保存状态
        // Restore instance state
        if (pendingActions.shouldRestoreInstanceState()) {
            if (r.isPersistable()) {
                if (r.state != null || r.persistentState != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                            r.persistentState);
                }
            } else if (r.state != null) {
                mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
            }
        }

// 是否调用 postOnCreate,这里满足
        // Call postOnCreate()
        if (pendingActions.shouldCallOnPostCreate()) {
            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnPostCreate(activity, r.state,
                        r.persistentState);
            } else {
                mInstrumentation.callActivityOnPostCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString()
                                + " did not call through to super.onPostCreate()");
            }
        }
// 更新为可见 updateVisibility
        updateVisibility(r, true /* show */);
        mSomeActivitiesChanged = true;
    }

// 更新为可见 updateVisibility

    private void updateVisibility(ActivityClientRecord r, boolean show) {
        View v = r.activity.mDecor;
        if (v != null) {
            if (show) {
                if (!r.activity.mVisibleFromServer) {
                    r.activity.mVisibleFromServer = true;
                    mNumVisibleActivities++;
                    if (r.activity.mVisibleFromClient) {
// 调用 activity 的 makeVisible 方法
                        r.activity.makeVisible();
                    }
                }

// 调用 activity 的 makeVisible 方法

    void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();

// WindowManagerImpl 增加 view ,mDecor为 DecorView
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

//  1-5-2-2)然后执行 ResumeActivityItem的 execute 和 postExecute

/frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java

执行 onresume 会打印对应 trace :activityResume 

    @Override
    public void execute(ClientTransactionHandler client, ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");

// 执行 handleResumeActivity
        client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
                "RESUME_ACTIVITY");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }


// 最后执行该流程,看起来和退出动画相关
    @Override
    public void postExecute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        // TODO(lifecycler): Use interface callback instead of actual implementation.
        ActivityClient.getInstance().activityResumed(token, client.isHandleSplashScreenExit(token));
    }

// 执行 handleResumeActivity

窗口的添加从Activity::makeVisible开始,由WindowManagerImpl委托给WindowManagerGlobal处理,WindowManagerGlobal内部的mViewsmRootsmParamsmDyingViews分别管理窗口的试图、主线程、布局参数以及死亡过程中的视图;ViewRootImpl持有Session的代理端与WMS通信;

/frameworks/base/core/java/android/app/ActivityThread.java

    @Override
    public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            boolean isForward, String reason) {

        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

// 先执行 performResumeActivity
        if (!performResumeActivity(r, finalStateRequest, reason)) {
            return;
        }


        final Activity a = r.activity;

        final int forwardBit = isForward
                ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

// mStartedActivity在 performResumeActivity 设置为 false
// willBeVisible  为 true
        boolean willBeVisible = !a.mStartedActivity;
        if (!willBeVisible) {
            willBeVisible = ActivityClient.getInstance().willActivityBeVisible(
                    a.getActivityToken());
        }
        if (r.window == null && !a.mFinished && willBeVisible) {

// 获取的对象是: PhoneWindow
            r.window = r.activity.getWindow();
// decor 是 new DecorView 对象
            View decor = r.window.getDecorView();

// DecorView 设置不可见
            decor.setVisibility(View.INVISIBLE);

// 在lauchactivity时候分析:activity.getWindowManager 是 WindowManagerImpl
            ViewManager wm = a.getWindowManager();
            WindowManager.LayoutParams l = r.window.getAttributes();

// 设置 activity 的 mDecor 为:DecorView 对象,先 install。。。
            a.mDecor = decor;

// 这里设置 layout 的类型为 TYPE_BASE_APPLICATION
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                // Normally the ViewRoot sets up callbacks with the Activity
                // in addView->ViewRootImpl#setView. If we are instead reusing
                // the decor view we have to notify the view root that the
                // callbacks may have changed.
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;

// addview 流程
                    wm.addView(decor, l);
                } else {
                    // The activity will get a callback for this {@link LayoutParams} change
                    // earlier. However, at that time the decor will not be set (this is set
                    // in this method), so no action will be taken. This call ensures the
                    // callback occurs with the decor set.
                    a.onWindowAttributesChanged(l);
                }
            }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }

4870          if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {

4888              r.activity.mVisibleFromServer = true;
4889              mNumVisibleActivities++;
4890              if (r.activity.mVisibleFromClient) {
4891                  r.activity.makeVisible();
4892              }
4893          }

// 先执行 performResumeActivity

    @VisibleForTesting
    public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            String reason) {

        if (r.getLifecycleState() == ON_RESUME) {
// finalStateRequest 为 true
            if (!finalStateRequest) {

            return false;
        }
        if (finalStateRequest) {
            r.hideForNow = false;
            r.activity.mStartedActivity = false;
        }
        try {
            r.activity.onStateNotSaved();
            r.activity.mFragments.noteStateNotSaved();
            checkAndBlockForNetworkAccess();
            if (r.pendingIntents != null) {
                deliverNewIntents(r, r.pendingIntents);
                r.pendingIntents = null;
            }
            if (r.pendingResults != null) {
                deliverResults(r, r.pendingResults, reason);
                r.pendingResults = null;
            }
// 回调 on_resume
            r.activity.performResume(r.startsNotResumed, reason);

            r.state = null;
            r.persistentState = null;
// 设置状态为 ON_RESUME
            r.setState(ON_RESUME);

            reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException("Unable to resume activity "
                        + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
            }
        }
        return true;
    }

addView  相关的调用栈

WindowManagerImpl.addView()
    new ViewRoot
    // 保存到 mViews  mRoots  mParams
    ViewRoot.setView(xx)
        requestLayout // 检查主线程
            scheduleTraversals
                sendEmptyMessage
                handleMessage
                    performTraversals  // 2.11 测量 布局 绘制
                        ViewRoot.relayoutWindow
                            IWindowSession.relayout // 参考relayout的调用栈
                        draw
                            View.draw
                        scheduleTralScheduled // try again
        mWindowSession.addToDisplay // 2.15 与requestLayout同级
        // sWindowSession.add
            WMS.addWindow // 2.16
                new WindowState // 
                WindowState.attach // 
                    Session.windowAddedLocked
                        new SurfaceSession // 开辟一块内存,由SurfaceFlinger进行混合处理

 wm.addView(decor, l) 流程

 // WindowManagerImpl 增加 view ,mDecor为 DecorView

/frameworks/base/core/java/android/view/WindowManagerImpl.java

    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();

    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyTokens(params);

// WindowManagerGlobal 增加 view,mParentWindow 为 PhoneWindow
        mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                mContext.getUserId());
    }

// WindowManagerGlobal 增加 view,mParentWindow 为 PhoneWindow

/frameworks/base/core/java/android/view/WindowManagerGlobal.java

// WindowManagerGlobal  是单例模式
    @UnsupportedAppUsage
    public static WindowManagerGlobal getInstance() {
        synchronized (WindowManagerGlobal.class) {
            if (sDefaultWindowManager == null) {
                sDefaultWindowManager = new WindowManagerGlobal();
            }
            return sDefaultWindowManager;
        }
    }

=========
    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
。。。。。

        ViewRootImpl root;
        View panelParentView = null;

....

            int index = findViewLocked(view, false);
            if (index >= 0) {
                if (mDyingViews.contains(view)) {
                    // Don't wait for MSG_DIE to make it's way through root's queue.
                    mRoots.get(index).doDie();
....

// 1-5-2-1-1)创建 ViewRootImpl 对象
            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

// 将 DecorView 放到 mViews 数组中
            mViews.add(view);

// 将 ViewRootImpl 放到 mRoots 数组中
            mRoots.add(root);
            mParams.add(wparams);

            try {

// 1-5-2-2)ViewRootImpl 设置  view,为 DecorView,两者关联
                root.setView(view, wparams, panelParentView, userId);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

// 1-5-2-1-1)创建 ViewRootImpl 对象

/frameworks/base/core/java/android/view/ViewRootImpl.java

    public ViewRootImpl(Context context, Display display) {

// getWindowSession 获取为 IWindowSession ,与 wms 通信,对象为 wm/Session.java
// 不使用 useSfChoreographer 
        this(context, display, WindowManagerGlobal.getWindowSession(),
                false /* useSfChoreographer */);
    }


    public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
            boolean useSfChoreographer) {
        mContext = context;
// 缓存 session 与 wms 通信
        mWindowSession = session;
        mDisplay = display;
        mBasePackageName = context.getBasePackageName();
        mThread = Thread.currentThread();
        mLocation = new WindowLeaked(null);
        mLocation.fillInStackTrace();
        mWidth = -1;
        mHeight = -1;
        mDirty = new Rect();
        mTempRect = new Rect();
        mVisRect = new Rect();
        mWinFrame = new Rect();

// mWindow  为 W 对象
        mWindow = new W(this);
        mLeashToken = new Binder();
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
        mViewVisibility = View.GONE;
        mTransparentRegion = new Region();
        mPreviousTransparentRegion = new Region();
        mFirst = true; // true for the first time the view is added
        mPerformContentCapture = true; // also true for the first time the view is added
        mAdded = false;

// 创建 View.AttachInfo 对象,传入 WindowSession,
        mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
                context);
        mCompatibleVisibilityInfo = new SystemUiVisibilityInfo();
        mAccessibilityManager = AccessibilityManager.getInstance(context);
        mAccessibilityManager.addAccessibilityStateChangeListener(
                mAccessibilityInteractionConnectionManager, mHandler);
        mHighContrastTextManager = new HighContrastTextManager();
        mAccessibilityManager.addHighTextContrastStateChangeListener(
                mHighContrastTextManager, mHandler);
        mViewConfiguration = ViewConfiguration.get(context);
        mDensity = context.getResources().getDisplayMetrics().densityDpi;
        mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
        mFallbackEventHandler = new PhoneFallbackEventHandler(context);

// 创建 Choreographer 对象
        mChoreographer = useSfChoreographer
                ? Choreographer.getSfInstance() : Choreographer.getInstance();
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
        mInsetsController = new InsetsController(new ViewRootInsetsControllerHost(this));

。。。。

    }

ViewRootImp 与 Session 的关系:

ViewRootImpl获取Session的代理类,通过Binder::IPC通信;
Session持有WMS服务;
InputStage为事件传递相关的类,管理窗口焦点focus;
W代表当前操作的窗口, 是ViewRootImpl的内部类,且持有ViewRootImpl的弱引用

// 1-5-2-2)ViewRootImpl 设置  view,为 DecorView,两者关联

root.setView(view, wparams, panelParentView, userId)

/frameworks/base/core/java/android/view/ViewRootImpl.java

    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
        synchronized (this) {
            if (mView == null) {
// 缓存 decorview
                mView = view;
。。。
                mSoftInputMode = attrs.softInputMode;
                mWindowAttributesChanged = true;

// 设置 mRootView 为 decorview
                mAttachInfo.mRootView = view;
                mAttachInfo.mScalingRequired = mTranslator != null;
                mAttachInfo.mApplicationScale =
                        mTranslator == null ? 1.0f : mTranslator.applicationScale;
                if (panelParentView != null) {
                    mAttachInfo.mPanelParentWindowToken
                            = panelParentView.getApplicationWindowToken();
                }
                mAdded = true;

。。。。。
                // Schedule the first layout -before- adding to the window
                // manager, to make sure we do the relayout before receiving
                // any other events from the system.
// 1)请求vysnc,走绘制三大流程:requestLayout
                requestLayout();

。。。。
                try {
                    mOrigWindowType = mWindowAttributes.type;
                    mAttachInfo.mRecomputeGlobalAttributes = true;
                    collectViewAttributes();
                    adjustLayoutParamsForCompatibility(mWindowAttributes);
                    controlInsetsForCompatibility(mWindowAttributes);

// 2)与wms 通信,增加 window:addToDisplayAsUser
                    res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), userId,
                            mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,
                            mTempControls);

// 1)请求vysnc,走绘制三大流程:requestLayout

    @Override
    public void requestLayout() {

// 如果没有走 performLayout 流程
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

===========
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
// 消息同步屏障机制
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 给 Choreographer 编舞者发送 CALLBACK_TRAVERSAL 消息,请求一个 vsync,然后主线程走绘制三大流程
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }

// 2)与wms 通信,增加 window:addToDisplayAsUser

/frameworks/base/services/core/java/com/android/server/wm/Session.java

// session 作为连接 wms 的中介
    @Override
    public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, int userId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
                requestedVisibility, outInputChannel, outInsetsState, outActiveControls);
    }

/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, InsetsState requestedVisibility,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls) {
        Arrays.fill(outActiveControls, null);
        int[] appOp = new int[1];
        final boolean isRoundedCornerOverlay = (attrs.privateFlags
                & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;

// PhoneWindowManager 做权限检查,layout 的参数类型是 TYPE_BASE_APPLICATION
// PhoneWindowManager 也是个比较重要的类
        int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
                appOp);
        if (res != ADD_OKAY) {
            return res;
        }

        WindowState parentWindow = null;
        final int callingUid = Binder.getCallingUid();
        final int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        final int type = attrs.type;

        synchronized (mGlobalLock) {
            if (!mDisplayReady) {
                throw new IllegalStateException("Display has not been initialialized");
            }

// 2-1) 创建或者获取 DisplayContent 对象 getDisplayContentOrCreate
            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);

.....
// type 为:TYPE_BASE_APPLICATION,不满足下列条件
            if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
                parentWindow = windowForClientLocked(null, attrs.token, false);

。。。
            ActivityRecord activity = null;

// hasParent  为false
            final boolean hasParent = parentWindow != null;

// 没有执行 addWindowToken,返回的 token 为null
            WindowToken token = displayContent.getWindowToken(
                    hasParent ? parentWindow.mAttrs.token : attrs.token);

            final int rootType = hasParent ? parentWindow.mAttrs.type : type;
            boolean addToastWindowRequiresToken = false;
            final IBinder windowContextToken = attrs.mWindowContextToken;

            if (token == null) {
。。。
                } else if (mWindowContextListenerController.hasListener(windowContextToken)) {

//  2-2) 执行下列流程,创建 WindowToken 对象
                } else {
                    final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                    token = new WindowToken.Builder(this, binder, type)
                            .setDisplayContent(displayContent)
                            .setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
                            .setRoundedCornerOverlay(isRoundedCornerOverlay)
                            .build();
                }

。。。。一些权限检查
。。。。

//  2-3) 创建 WindowState 对象
            final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], attrs, viewVisibility, session.mUid, userId,
                    session.mCanAddInternalSystemWindow);
            if (win.mDeathRecipient == null) {
                // Client has apparently died, so there is no reason to
                // continue.
                ProtoLog.w(WM_ERROR, "Adding window client %s"
                        + " that is dead, aborting.", client.asBinder());
                return WindowManagerGlobal.ADD_APP_EXITING;
            }

            if (win.getDisplayContent() == null) {
                ProtoLog.w(WM_ERROR, "Adding window to Display that has been removed.");
                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
            }

            final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();

// DisplayPolicy  执行 adjustWindowParamsLw 调整 参数,为 TYPE_BASE_APPLICATION没有调整
            displayPolicy.adjustWindowParamsLw(win, win.mAttrs);
            win.updateRequestedVisibility(requestedVisibility);

            res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
            if (res != ADD_OKAY) {
                return res;
            }

// 2-4) WinState去 打开InputChannel
            final boolean openInputChannels = (outInputChannel != null
                    && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
            if  (openInputChannels) {
                win.openInputChannel(outInputChannel);
            }

            if (mUseBLAST) {
                res |= WindowManagerGlobal.ADD_FLAG_USE_BLAST;
            }

// 在 mWinAddedSinceNullFocus 数组增加这个 winstate
            if (displayContent.mCurrentFocus == null) {
                displayContent.mWinAddedSinceNullFocus.add(win);
            }

            if (excludeWindowTypeFromTapOutTask(type)) {
                displayContent.mTapExcludedWindows.add(win);
            }

// 调用 Session 创建 SurfaceSession对象
            win.attach();
// 将 winstate 放到 map 中
            mWindowMap.put(client.asBinder(), win);
            win.initAppOpsState();

            final boolean suspended = mPmInternal.isPackageSuspended(win.getOwningPackage(),
                    UserHandle.getUserId(win.getOwningUid()));
            win.setHiddenWhileSuspended(suspended);

            final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
            win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);

            final ActivityRecord tokenActivity = token.asActivityRecord();
            if (type == TYPE_APPLICATION_STARTING && tokenActivity != null) {
                tokenActivity.mStartingWindow = win;
                ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
                        activity, win);
            }

            boolean imMayMove = true;
// 2-5) 在 winstate 的WinToken 中增加自己:addWindow
            win.mToken.addWindow(win);
            displayPolicy.addWindowLw(win, attrs);

            final WindowStateAnimator winAnimator = win.mWinAnimator;
// 设置为进入到动画
            winAnimator.mEnterAnimationPending = true;
            winAnimator.mEnteringAnimation = true;

// 看起来和动画相关
            if (activity != null && activity.isVisible()
                    && !prepareWindowReplacementTransition(activity)) {
                // If not, check if need to set up a dummy transition during display freeze
                // so that the unfreeze wait for the apps to draw. This might be needed if
                // the app is relaunching.
                prepareNoneTransitionForRelaunching(activity);
            }
。。。。

            boolean focusChanged = false;
            if (win.canReceiveKeys()) {

// 更新焦点
                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
                if (focusChanged) {
                    imMayMove = false;
                }
            }

            win.getParent().assignChildLayers();

            if (focusChanged) {
                displayContent.getInputMonitor().setInputFocusLw(displayContent.mCurrentFocus,
                        false /*updateInputWindows*/);
            }
            displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);

            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addWindow: New client %s"
                    + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5));

            if (win.isVisibleOrAdding() && displayContent.updateOrientation()) {
                displayContent.sendNewConfiguration();
            }

            // This window doesn't have a frame yet. Don't let this window cause the insets change.
            displayContent.getInsetsStateController().updateAboveInsetsState(
                    win, false /* notifyInsetsChanged */);

            getInsetsSourceControls(win, outActiveControls);
        }

// 2-1) 创建或者获取 DisplayContent 对象 getDisplayContentOrCreate

    RootWindowContainer mRoot;

    private DisplayContent getDisplayContentOrCreate(int displayId, IBinder token) {
        if (token != null) {
// mRoot 为 RootWindowContainer,这里返回是 null
            final WindowToken wToken = mRoot.getWindowToken(token);
            if (wToken != null) {
                return wToken.getDisplayContent();
            }
        }

// 调用 RootWindowContainer,返回 DisplayContent  对象
        return mRoot.getDisplayContentOrCreate(displayId);
    }

=======

    // TODO: Look into consolidating with getDisplayContent()
    @Nullable
    DisplayContent getDisplayContentOrCreate(int displayId) {
        DisplayContent displayContent = getDisplayContent(displayId);
        if (displayContent != null) {
            return displayContent;
        }

/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    /** Returns the window token for the input binder if it exist in the system. */
    WindowToken getWindowToken(IBinder binder) {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
// 如下分析,setWindowManager创建了DisplayContent, 获取到 DisplayContent
            final DisplayContent dc = mChildren.get(i);

// 需要调用 addWindowToken,才有对应的 WindowToken
            final WindowToken wtoken = dc.getWindowToken(binder);
            if (wtoken != null) {
                return wtoken;
            }
        }
        return null;
    }

=========
// mChildren 是再父类WindowContainer.java addChild 赋值的

514      protected void addChild(E child, Comparator<E> comparator) {
515          if (!child.mReparenting && child.getParent() != null) {
516              throw new IllegalArgumentException("addChild: container=" + child.getName()
517                      + " is already a child of container=" + child.getParent().getName()
518                      + " can't add to container=" + getName());
519          }
520  
521          int positionToAdd = -1;
522          if (comparator != null) {
523              final int count = mChildren.size();
524              for (int i = 0; i < count; i++) {
525                  if (comparator.compare(child, mChildren.get(i)) < 0) {
526                      positionToAdd = i;
527                      break;
528                  }
529              }
530          }
531  
532          if (positionToAdd == -1) {
533              mChildren.add(child);
534          } else {
535              mChildren.add(positionToAdd, child);
536          }

========
// 在 系统进程初始化的时候有 setWindowManager
    void setWindowManager(WindowManagerService wm) {
        mWindowManager = wm;
        mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
        mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);

        final Display[] displays = mDisplayManager.getDisplays();
        for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
            final Display display = displays[displayNdx];
// 创建 DisplayContent 对象
            final DisplayContent displayContent = new DisplayContent(display, this);
// 增加这个 child
            addChild(displayContent, POSITION_BOTTOM);
            if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
                mDefaultDisplay = displayContent;
            }
        }

综上 // 调用 RootWindowContainer,返回 DisplayContent  对象,是在RootWindowContainer调用 setWindowManager创建的

  • 关于 token 的值:

sysdump 的 token 值:

WINDOW MANAGER TOKENS (dumpsys window tokens)
  All tokens:
  Display #0
  WindowToken{e9d62ae android.os.BinderProxy@37184b0}
  WindowToken{6647845 android.os.Binder@c5f70bc}
  ActivityRecord{e67d959 u0 com.android.dialer/.main.impl.MainActivity t50}
  ActivityRecord{8fa9411 u0 com.android.settings/.Settings t53}
  WindowToken{b0ea09f android.os.BinderProxy@b95fa3e}
  WindowToken{7eca95e android.os.BinderProxy@853299d}
  ActivityRecord{7ed7a5 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t49}
  ActivityRecord{f88a6c9 u0 com.android.settings/.SubSettings t53}
  WindowToken{d880889 android.os.BinderProxy@7449253}
  ActivityRecord{bdf7fde u0 com.android.settings/.SubSettings t53}
  ActivityRecord{243a4ac u0 com.sprd.logmanager/.logui.LogMainActivity t54}
  WallpaperWindowToken{78f6c2f token=android.os.Binder@537a0e}
  ActivityRecord{b742969 u0 com.sprd.engineermode/.EngineerModeActivity t55}
  WindowToken{5a839c7 android.os.BinderProxy@55f65e1}

/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

6146      private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) {
6147          pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)");
6148          mRoot.dumpTokens(pw, dumpAll);
6149      }

===========
/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

    void dumpTokens(PrintWriter pw, boolean dumpAll) {
        pw.println("  All tokens:");
        for (int i = mChildren.size() - 1; i >= 0; --i) {

// 调用对应的child
            mChildren.get(i).dumpTokens(pw, dumpAll);
        }
    }

=========
 /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

   void dumpTokens(PrintWriter pw, boolean dumpAll) {
        if (mTokenMap.isEmpty()) {
            return;
        }
        pw.println("  Display #" + mDisplayId);
// mTokenMap 是在 addWindowToken 中添加的
        final Iterator<WindowToken> it = mTokenMap.values().iterator();
        while (it.hasNext()) {
            final WindowToken token = it.next();
            pw.print("  ");
// 直接对应的 tostring 方法
            pw.print(token);

// 不是 dumpall
            if (dumpAll) {
                pw.println(':');
                token.dump(pw, "    ", dumpAll);
            } else {
                pw.println();
            }
        }

-------
// 这里去添加对应的 token
    void addWindowToken(IBinder binder, WindowToken token) {
        final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token);

        mTokenMap.put(binder, token);

调用链为: 

WinndowManagerService ==> RootWindowContainer ==> DisplayContent ==> WindowToken

 ActivityRecord、WallpaperWindowToken 继承了 WindowToken

mTokenMap保存WindowToken 有:WindowToken、ActivityRecord、WallpaperWindowToken

//  2-2) 执行下列流程,创建 WindowToken 对象

/frameworks/base/services/core/java/com/android/server/wm/WindowToken.java

    static class Builder {
        private final WindowManagerService mService;
        private final IBinder mToken;
        @WindowType
        private final int mType;

        private boolean mPersistOnEmpty;
        private DisplayContent mDisplayContent;
        private boolean mOwnerCanManageAppTokens;
        private boolean mRoundedCornerOverlay;
        private boolean mFromClientToken;
        @Nullable
        private Bundle mOptions;

        Builder(WindowManagerService service, IBinder token, int type) {
            mService = service;
            mToken = token;
            mType = type;
        }
.。。。
        WindowToken build() {
            return new WindowToken(mService, mToken, mType, mPersistOnEmpty, mDisplayContent,
                    mOwnerCanManageAppTokens, mRoundedCornerOverlay, mFromClientToken, mOptions);
        }

//  2-3) 创建 WindowState 对象

/frameworks/base/services/core/java/com/android/server/wm/WindowState.java

IWindow c 为:ViewRootImpl 的 final W mWindow,与客户端通信

WindowToken token,: 为 WindowToken
WindowState parentWindow: 为null

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
            int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow) {
        this(service, s, c, token, parentWindow, appOp, a, viewVisibility, ownerId, showUserId,
                ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
                    @Override
                    public void wakeUp(long time, @WakeReason int reason, String details) {
                        service.mPowerManager.wakeUp(time, reason, details);
                    }

                    @Override
                    public boolean isInteractive() {
                        return service.mPowerManager.isInteractive();
                    }
                });
    }

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, WindowManager.LayoutParams a, int viewVisibility,
            int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow,
            PowerManagerWrapper powerManagerWrapper) {
        super(service);
// SurfaceControl.Transaction 对象
        mTmpTransaction = service.mTransactionFactory.get();
        mSession = s;
// viewrootimpl 的 W
        mClient = c;
        mAppOp = appOp;
        mToken = token;
// 为 null
        mActivityRecord = mToken.asActivityRecord();
        mOwnerUid = ownerId;
        mShowUserId = showUserId;
        mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
        mWindowId = new WindowId(this);
        mAttrs.copyFrom(a);
        mLastSurfaceInsets.set(mAttrs.surfaceInsets);
        mViewVisibility = viewVisibility;

// policy是 PhoneWindowManager
        mPolicy = mWmService.mPolicy;
        mContext = mWmService.mContext;
        DeathRecipient deathRecipient = new DeathRecipient();
        mPowerManagerWrapper = powerManagerWrapper;
        mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
        mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle(
                mActivityRecord != null
                        ? mActivityRecord.getInputApplicationHandle(false /* update */) : null,
                getDisplayId()));
        mInputWindowHandle.setOwnerPid(s.mPid);
        mInputWindowHandle.setOwnerUid(s.mUid);
        mInputWindowHandle.setName(getName());
        mInputWindowHandle.setPackageName(mAttrs.packageName);
        mInputWindowHandle.setLayoutParamsType(mAttrs.type);

// 。。。。。。。
        } else {
            // The multiplier here is to reserve space for multiple
            // windows in the same type layer.

// 这里乘以 10000 然后加 TYPE_LAYER_OFFSET = 1000==》 11000
            mBaseLayer = mPolicy.getWindowLayerLw(this)
                    * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
            mSubLayer = 0;
            mIsChildWindow = false;
            mLayoutAttached = false;
            mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
                    || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
            mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
        }
// 为 false
        mIsFloatingLayer = mIsImWindow || mIsWallpaper;

        if (mActivityRecord != null && mActivityRecord.mShowForAllUsers) {
            // Windows for apps that can show for all users should also show when the device is
            // locked.
            mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
        }

// 创建 WindowStateAnimator 对象
        mWinAnimator = new WindowStateAnimator(this);
        mWinAnimator.mAlpha = a.alpha;

        mRequestedWidth = 0;
        mRequestedHeight = 0;
        mLastRequestedWidth = 0;
        mLastRequestedHeight = 0;
        mLayer = 0;
        mOverrideScale = mWmService.mAtmService.mCompatModePackages.getCompatScale(
                mAttrs.packageName, s.mUid);

。。。。

// 2-4) WinState去 打开InputChannel

/frameworks/base/services/core/java/com/android/server/wm/WindowState.java

    void openInputChannel(InputChannel outInputChannel) {
        if (mInputChannel != null) {
            throw new IllegalStateException("Window already has an input channel.");
        }
// 获取名字
        String name = getName();

// 调用 wms 的inputmanagerservice 去 创建channel: nativeCreateInputChannel
        mInputChannel = mWmService.mInputManager.createInputChannel(name);
        mInputChannelToken = mInputChannel.getToken();
        mInputWindowHandle.setToken(mInputChannelToken);

// 将其token 放入到 wms 的焦点map 中
        mWmService.mInputToWindowMap.put(mInputChannelToken, this);
        if (outInputChannel != null) {
            mInputChannel.copyTo(outInputChannel);
        } else {

// 2-5) 在 winstate 的WinToken 中增加自己:addWindow

/frameworks/base/services/core/java/com/android/server/wm/WindowToken.java

    void addWindow(final WindowState win) {
        ProtoLog.d(WM_DEBUG_FOCUS,
                "addWindow: win=%s Callers=%s", win, Debug.getCallers(5));

// 这里为 false
        if (win.isChildWindow()) {
            // Child windows are added to their parent windows.
            return;
        }

// 先创建个 SurfaceControl,设置了 setSurfaceControl,SurfaceControl
        if (mSurfaceControl == null) {
            createSurfaceControl(true /* force */);
        }
        if (!mChildren.contains(win)) {
            ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);

// 调用父类将win 增加到 mChildren 中
            addChild(win, mWindowComparator);
            mWmService.mWindowsChanged = true;
            // TODO: Should we also be setting layout needed here and other places?
        }
    }

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

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

相关文章

ESP-C2模组 AT示例程序

ESP32C2 AT固件使用 ESP32 C2模组&#xff0c;如图1-1所示 图1-1 ESP32 C2模组 ESP32 C2开发板&#xff0c;如图1-2所示 图1-2 ESP32 C2开发 方案亮点 1、完整的 WiFi 子系统&#xff0c;符合 IEEE 802.11b/g/n 协议&#xff0c;具有 Station 模式、SoftAP 模式、SoftAP Stat…

2023电商运营课程培训课程干货

​电商运营是当今社会最为火热的词汇之一&#xff0c;在各个领域有着广泛的运用。各种途径的线上销售使得产品的销售以及品牌的推广变得更加容易&#xff0c;因此越来越多的人选择从事电商运营。而电商运营的成功离不开专业的培训&#xff0c;为此许多机构推出了电商运营课程培…

python数据结构详解

Python是一种高级编程语言&#xff0c;它具有简单易学的语法和强大的数据结构。在Python中&#xff0c;数据结构是指一组数据和与之相关的操作的集合。Python提供了许多数据结构&#xff0c;包括列表、元组、字典、集合和字符串。本文将深入介绍Python中的数据结构&#xff0c;…

离散数学题目收集整理练习(期末过关进度40%)

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;离散数学考前复习&#xff08;知识点题&#xff09; &#x1f353;专栏&#xff1a;概率论期末速成&#xff08;一套卷&#xff09; &#x1f433;专栏&#xff1a;数字电路考前复习 ✨博主的其他文章&#xff1a;点击…

ubuntu18.04设置自启动踩坑贴(拿来即用)---全网搜索半天都没有,ChatGPT回答都是有问题的!!

前言&#xff1a;其实很简单&#xff0c;全网的资料实在坑太多&#xff08;无语&#xff09;&#xff0c;有一篇还不错&#xff0c;我大多数借鉴这篇https://cloud.tencent.com/developer/article/1803805&#xff0c;但直接用貌似也不通&#xff0c;这边记录了我的实测可跑通版…

【AIGC】BaiChuan7B开源大模型介绍、部署以及创建接口服务

模型介绍 baichuan-7B是由百川智能开发的一个开源的大规模预训练模型。基于Transformer结构&#xff0c;在大约1.2万亿tokens上训练的70亿参数模型&#xff0c;支持中英双语&#xff0c;上下文窗口长度为4096。在标准的中文和英文权威benchmark&#xff08;C-EVAL/MMLU&#x…

游戏革命2023:AIGC拯救游戏厂商

文明史即工具史&#xff0c;纵观人类社会的演化&#xff0c;每一次的加速迭代&#xff0c;都有赖于关键性的技术突破。 前有蒸汽机到电力普及的生产力大爆发&#xff0c;以及计算机、互联网的诞生打开新世界&#xff0c;如今AIGC将再次推动先进技术工具的变革。 随着ChatGPT的…

​​​​​​​微信怎么快捷回复?

怎么快速的回复客户一直问的问题&#xff0c;还在一个个回&#xff0c;我直接把常问问题的回复编辑好&#xff0c;直接一秒搞定回复&#xff0c;客户还以为我敲字速度杠杠的 #快捷回复 #微信怎么快速回复信息 #话术

深入理解Java虚拟机jvm-对象的内存布局

对象的内存布局 对象头&#xff08;Header&#xff09;实例数据&#xff08;Instance Data&#xff09;对齐填充&#xff08;Padding&#xff09; 在HotSpot虚拟机里&#xff0c;对象在堆内存中的存储布局可以划分为三个部分&#xff1a;对象头&#xff08;Header&#xff09;、…

简要介绍 | 计算机视觉中的开放词汇:挑战与未来

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对计算机视觉中的开放词汇(open vocabulary)进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 注2&#xff1a;"简要介绍"系列的所有创作均使用了AIGC工具辅助 计算机视觉中的开放词汇&…

ASP.NET Core MVC 从入门到精通之鉴权授权基础

随着技术的发展&#xff0c;ASP.NET Core MVC也推出了好长时间&#xff0c;经过不断的版本更新迭代&#xff0c;已经越来越完善&#xff0c;本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容&#xff0c;适用于初学者&#xff0c;在校毕业生&#xff0c…

在 ZBrush、Substance 3D Painter 和 UE5 中创作警探角色(P2)

大家好&#xff0c;下篇分享咱们继续来说警探角色的重新拓扑、UV、材质贴图和渲染处理。 重新拓扑/UV 这是对我来说最不有趣的部分——重新拓扑。它显然是实时角色中非常重要的一部分&#xff0c;不容忽视&#xff0c;因为它会影响大量的 UV、绑定和后期渲染&#xff0c;这里…

从零开始 Spring Boot 42:异步执行

从零开始 Spring Boot 42&#xff1a;异步执行 图源&#xff1a;简书 (jianshu.com) 在之前的文章中&#xff0c;我多次介绍过在 Spring 中如何使用Async注解让方法调用变成“异步执行”&#xff1a; 在这篇文章中&#xff0c;介绍了如何让定时任务使用Async变成异步执行。在…

​达梦三种主备集群介绍

DM主备守护集群分为实时主备、读写分离集群、MPP主备集群。基于redo日志实现&#xff0c;不同的集群采用不同的redo日志归档类型。 实时主备&#xff1a; 实时主备系统由主库、实时备库、守护进程和监视器组成。通过部署实时主备系统&#xff0c;可以及时检测并处理各种硬件故…

GIS大数据处理框架sedona(塞多纳)编程入门指导

GIS大数据处理框架sedona(塞多纳)编程入门指导 简介 Apache Sedona™是一个用于处理大规模空间数据的集群计算系统。Sedona扩展了现有的集群计算系统&#xff0c;如Apache Spark和Apache Flink&#xff0c;使用一组开箱即用的分布式空间数据集和空间SQL&#xff0c;可以有效地…

【备战秋招】每日一题:2023.05-B卷-华为OD机试 - 2023.05-B卷-华为OD机试 - AI面板识别

2023大厂笔试模拟练习网站&#xff08;含题解&#xff09; www.codefun2000.com 最近我们一直在将收集到的各种大厂笔试的解题思路还原成题目并制作数据&#xff0c;挂载到我们的OJ上&#xff0c;供大家学习交流&#xff0c;体会笔试难度。现已录入200道互联网大厂模拟练习题&a…

【双曲几何学 02】什么是极点和极线?

一、说明 Pole and polar 对于几何学&#xff0c;是普遍的概念。可能高中就学过&#xff0c;问题是在双曲几何又用到这个概念&#xff0c;因此&#xff0c;这里再次强调理解这个概念 。为后边学习双曲几何扫清障碍。 二、基本概念 在几何学中&#xff0c;极点和极线分别是相对于…

NetSuite SuiteQlet 功能包

目录 1.前言 2.功能说明 2.1术语 2.2功能概述 2.3逻辑阐释 3.安装 4.权限配置 ​​​5.操作指南 5.1Query查询 5.2Chart图表 5.3Dashboard仪表板发布 6.注意事项 7.视频链接 1.前言 SuiteQL是NetSuite数据分析框架中进行数据查询的有力工具&#xff0c;使用得当则…

华为云CodeArtBuild减负!云端编译构建,让你的开发省时省力!

每一个剑客都需要一把趁手的利器&#xff0c;初学者如何利用编译软件&#xff1f;只需五分钟&#xff0c;带你体验软件开发的效率。 请注册华为云账号并完成实名认证&#xff0c;实验过程中请使用Chrome浏览器完成相关操作。 华为云账号注册步骤请参考&#xff1a; ​​http…

介质中的平面电磁波与色散效应

目录 理想介质中的平面电磁波 方程推导 解的讨论 ​​​​​​​瞬时形式 等相面 参数讨论 导电媒质中的均匀平面波 方程推导 解的讨论 波的特征分析 色散效应的讨论 理想介质中的平面电磁波 方程推导 已知两个方程 我们如果令 方程就可以化简为 这两个方程在数学…