Android 9.0 ActivityのOnPuseメソッド実行プロセス分析

19850 ワード

前の記事では、デスクトップアイコンをクリックしてActivityを起動するプロセス分析を分析しましたが、幅の都合でActivityを起動する過程で、前のActivity、つまりLauncherプロセスのLauncherというActivityのOnPauseメソッドは分析されていません.この記事ではActivityのOnPauseメソッドの実行過程を分析します.次に、前述のActivity StackSupervisorクラスのresumeTopActivity InnerLocked()を分析します.このメソッドの内部では、resumedActivityが存在するかどうかをチェックし、ある場合はresumedActivityのonPauseメソッドを先に実行し、起動するActivityのプロセスを実行します.
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
//          null 
       // ...

	//    Activity  , finish ,    Activity,       Activity,  next  null
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);

	// hasRunningActivity = true
        final boolean hasRunningActivity = next != null;

	// ...
	//     
        if (!hasRunningActivity) {
            
            return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
        }

        next.delayedResume = false;

        // ...

        mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

       // ...

        //        Resume   Activity ,     Activity  (  onPause  )
	//    AcivityA   ActivityB(   ActivityB process  ,ActivityB          ),  
	//   ActivityA    onPause  ,   ActivityB    app  (  ActivityB          ),
	//  ActivityB       ,     ActivityB,        ,       
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }

       // ...

        ActivityStack lastStack = mStackSupervisor.getLastStack();
	//      Activity       
        if (next.app != null && next.app.thread != null) {
            //...

            synchronized(mWindowManager.getWindowManagerLock()) {
                // This activity is now becoming visible.
		// ...

                boolean notUpdated = true;

                if (mStackSupervisor.isFocusedStack(this)) {
                    
                    notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
                            true /* markFrozenIfConfigChanged */, false /* deferResume */);
                }

                if (notUpdated) {
 
                    ActivityRecord nextNext = topRunningActivityLocked();
		    // ...
                    if (nextNext != next) {
                        // Do over!
			//    
                        mStackSupervisor.scheduleResumeTopActivities();
                    }
                    // ...
                    return true;
                }

		// ...
            }
            
           // ...
        } else {
            // Whoops, need to restart this activity!
	    //    Activity        
            // ...
	    //    
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        // ...
        return true;
}


final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
        ActivityRecord resuming, boolean pauseImmediately) {
	// ...
    ActivityRecord prev = mResumedActivity;

	// ...

    if (prev.app != null && prev.app.thread != null) {
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
        try {
            // ...
	    //     
            mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
                    PauseActivityItem.obtain(prev.finishing, userLeaving,
                            prev.configChangeFlags, pauseImmediately));
        }
	// ...
    } else {
       // ...
    }

    // ...

    if (mPausingActivity != null) {
        // ...
        
        if (pauseImmediately) {
            // ...
            completePauseLocked(false, resuming);
            return false;

        } else {
            schedulePauseTimeout(prev);
            return true;
        }

    } else {
        // ...
        if (resuming == null) {
            mStackSupervisor.resumeFocusedStackTopActivityLocked();
        }
        return false;
    }
}

startPausingLocked()このメソッドでは、ClientLifecycleManagerのscheduleTransactionメソッドが実行されます.入力された3番目のパラメータは、PauseActivity Itemのインスタンスオブジェクトであることに注意してください.次に、このメソッドの具体的な実装を見てみましょう.

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java

void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
        @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
    final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
            stateRequest);
    scheduleTransaction(clientTransaction);
}

private static ClientTransaction transactionWithState(@NonNull IApplicationThread client,
        @NonNull IBinder activityToken, @NonNull ActivityLifecycleItem stateRequest) {
    final ClientTransaction clientTransaction = ClientTransaction.obtain(client, activityToken);
    //    ,   stateRequest,  PauseActivityItem     
    clientTransaction.setLifecycleStateRequest(stateRequest);
    return clientTransaction;
}

void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    final IApplicationThread client = transaction.getClient();
    transaction.schedule();
    if (!(client instanceof Binder)) {
        transaction.recycle();
    }
}

scheduleTransactionメソッドをリロードした後、ClientTransactionのscheduleメソッドを呼び出します.次に、このメソッドの具体的な実装を見てみましょう.

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

このメソッドのmClientはIApplicationThreadタイプのオブジェクトであり、実際にはadilインタフェースであり、その具体的な実装クラスはApplicationThreadであり、コードはApplicationThreadクラスにジャンプして実行されます.次に、ApplicationThreadのscheduleTransactionメソッドの具体的な実装を見てみましょう.

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java

@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    ActivityThread.this.scheduleTransaction(transaction);
}

このメソッドの内部では、ClientTransactionHandlerクラスのscheduleTransactionメソッドも呼び出されます.次に、このメソッドの具体的な実装を見てみましょう.

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ClientTransactionHandler.java

void scheduleTransaction(ClientTransaction transaction) {
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

このメソッドは内部的にActivity ThreadクラスのsendMessageメソッドを呼び出し,Activity Threadクラスの内部クラスHはHandlerを継承し,最後にHクラスのhandleMessageメソッドを実行する.
// ...
case EXECUTE_TRANSACTION:
        final ClientTransaction transaction = (ClientTransaction) msg.obj;
        mTransactionExecutor.execute(transaction);
        if (isSystem()) {
            transaction.recycle();
        }
        break;
// ...


このメソッドの内部にはTransactionExecuterのexecuteメソッドも呼び出されています.次に、このメソッドの具体的な実装を見てみましょう.

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        
        executeCallbacks(transaction);

        executeLifecycleState(transaction);
        mPendingActions.clear();
        
}


public void executeCallbacks(ClientTransaction transaction) {
    final List callbacks = transaction.getCallbacks();
    if (callbacks == null) {
        // No callbacks to execute, return early.
        return;
    }
    log("Resolving callbacks");

    // ...

    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        log("Resolving callback: " + item);
        final int postExecutionState = item.getPostExecutionState();
        final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                item.getPostExecutionState());
        if (closestPreExecutionState != UNDEFINED) {
            cycleToPath(r, closestPreExecutionState);
        }

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

このメソッドの内部ではexecuteCallbacksが呼び出されます.ClientTransactionにcallbacksが追加されていないため、このメソッドの内部ではコールバックは実行されません.次にexecuteLifecycleState(transaction)を見ます.方法
private void executeLifecycleState(ClientTransaction transaction) {
     final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
     if (lifecycleItem == null) {
         return;
     }
     

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

     if (r == null) {
         return;
     }

     // Cycle to the state right before the final requested state.
     cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

     // Execute the final transition with proper parameters.
     lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
     lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
 }


private void cycleToPath(ActivityClientRecord r, int finish,
        boolean excludeLastState) {
    //  Launcher    onResume,  start 3
    final int start = r.getLifecycleState();
    log("Cycle from: " + start + " to: " + finish + " excludeLastState:" + excludeLastState);
    final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
    performLifecycleSequence(r, path);
}

private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            log("Transitioning to state: " + state);
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, mPendingActions);
                    break;
                case ON_RESUME:
                    mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                            r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                    break;
                case ON_PAUSE:
                    mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
                            false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                            "LIFECYCLER_PAUSE_ACTIVITY");
                    break;
                case ON_STOP:
                    mTransactionHandler.handleStopActivity(r.token, false /* show */,
                            0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
                            "LIFECYCLER_STOP_ACTIVITY");
                    break;
                case ON_DESTROY:
                    mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                            0 /* configChanges */, false /* getNonConfigInstance */,
                            "performLifecycleSequence. cycling to:" + path.get(size - 1));
                    break;
                case ON_RESTART:
                    mTransactionHandler.performRestartActivity(r.token, false /* start */);
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
            }
        }
 }

このメソッドの内部では、cycleToPathメソッドが実行されます.このメソッドの主な役割は、転送されたtargetState状態と現在の状態に基づいて、中間状態が存在するかどうかを計算し、存在する場合は、中間状態と転送された状態のライフサイクルのメソッドを順番に実行することです.例えば、現在のActivityを加えるとonResume状態にある場合、lifecycleItemはResumeActivity Itemタイプであり、lifecycleItemを通過する.getTargetState()は、対応する状態定数を取得します.この定数は3です.Activity LifecycleItemというクラスでは、public static final int ON_CREATE = 1; public static final int ON_START = 2; public static final int ON_RESUME = 3; public static final int ON_PAUSE = 4; public static final int ON_STOP = 5; public static final int ON_DESTROY = 6; public static final int ON_RESTART = 7;
ここでは現在の状態がonResume状態であると仮定するので,cycleToPathメソッド内部のstartの値は3,finishの値は4,なぜ4なのか.executeLifecycleStateメソッドでは、lifecycleItemは実はPauseActivity Itemであるため、PauseActivity Itemオブジェクトが取得するtargetStateの値は4である、このようにcycleToPathメソッドで計算すると、彼らの間に中間状態は存在しないので、mHelperを通過する.getLifecyclePathメソッドで取得したIntArrayの値は0です.getLifecyclePathメソッドの具体的な実装を見てみましょう.

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/servertransaction/TransactionExecutorHelper.java

@VisibleForTesting
public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState) {
    // ...

    mLifecycleSequence.clear();
	// finish = 4  start = 3,
    if (finish >= start) {
        for (int i = start + 1; i <= finish; i++) {
            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.
    if (excludeLastState && mLifecycleSequence.size() != 0) {
        mLifecycleSequence.remove(mLifecycleSequence.size() - 1);
    }

    return mLifecycleSequence;
}

この方法により,finishが4,startが3の場合,この方法が最後に返されるmLifecycleSequenceのsizeは0であるため,cycleToPath法は実際には何もしていないことが分かる.次に、executeLifecycleState()メソッドの具体的な実装について説明します.

private void executeLifecycleState(ClientTransaction transaction) {
    final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
    if (lifecycleItem == null) {
        return;
    }

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

    if (r == null) {
        return;
    }

    // ...
    cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

    lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
    lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

この方法の内部のcycleToPath方法を分析した後、lifecycleItemを見続けた.execute(mTransactionHandler, token, mPendingActions); この行のコードは、ClientLifecycleManagerクラスのtransactionWithStateメソッドを以前に分析したことがあるため、このlifecycleItemはPauseActivity Itemクラスのexecuteメソッドであり、このメソッドの具体的な実装を見てみましょう.

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/servertransaction/PauseActivityItem.java

@Override
public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
            "PAUSE_ACTIVITY_ITEM");
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

このメソッドのclientはちょうどClientTransactionHandlerであり,ClinetTransactionHandlerは抽象クラスであるため,このメソッドを実行するのはそのサブクラスActivity ThreadのhandlePauseActivityメソッドであり,Activity ThreadクラスのhandlePauseActivityメソッドを以下に示す.

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java

@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
        int configChanges, PendingTransactionActions pendingActions, String reason) {
    ActivityClientRecord r = mActivities.get(token);
    if (r != null) {
        if (userLeaving) {
            performUserLeavingActivity(r);
        }

        r.activity.mConfigChangeFlags |= configChanges;

	//     
        performPauseActivity(r, finished, reason, pendingActions);

        // Make sure any pending writes are now committed.
        if (r.isPreHoneycomb()) {
            QueuedWork.waitToFinish();
        }
        mSomeActivitiesChanged = true;
    }
}


private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
        PendingTransactionActions pendingActions) {
    // ...
    //     
    performPauseActivityIfNeeded(r, reason);

    ArrayList listeners;
    synchronized (mOnPauseListeners) {
        listeners = mOnPauseListeners.remove(r.activity);
    }
    int size = (listeners != null ? listeners.size() : 0);
    for (int i = 0; i < size; i++) {
        listeners.get(i).onPaused(r.activity);
    }

    final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
    if (oldState != null) {
        if (r.isPreHoneycomb()) {
            r.state = oldState;
        }
    }

    return shouldSaveState ? r.state : null;
}

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
   // ...

    try {
        r.activity.mCalled = false;
	//    
        mInstrumentation.callActivityOnPause(r.activity);
        if (!r.activity.mCalled) {
            throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
                    + " did not call through to super.onPause()");
        }
    }
    // ...
    r.setState(ON_PAUSE);
}

上記のperformPauseActivity IfNeedメソッドでは、InstrumentationのcallActivity OnPauseメソッドが実行されています.次に、このメソッドの具体的な実装を見てみましょう.
http://androidxref.com/9.0.0_r3/xref/art/test/Instrumentation/Instrumentation.java

public void callActivityOnPause(Activity activity) {
    activity.performPause();
}

このメソッドの内部では最終的にActivityのperformPauseメソッドが呼び出され、OnPauseメソッドが呼び出され、ActivityのOnPauseメソッドが実行されます.以上がActivityのonPasueメソッドの実行プロセス解析である.