Mobile Development 10 min read

Adapting Android P Activity Lifecycle Hooks for the 分身大师 Plugin Framework

This article explains how Android P refactors the Activity lifecycle handling, details the shift from LAUNCH_ACTIVITY messages to EXECUTE_TRANSACTION processing, and describes the necessary code adaptations for the 分身大师 framework to support dual‑open apps on Android P.

Qizhuo Club
Qizhuo Club
Qizhuo Club
Adapting Android P Activity Lifecycle Hooks for the 分身大师 Plugin Framework

Android P Activity Lifecycle Changes

分身大师 is a highly invasive plugin framework that directly runs user‑cloned apps, but its many hooks make it sensitive to system updates; changes in Android P’s framework, especially Activity lifecycle restructuring, require a series of adaptations.

1.1 ActivityThread Message Changes

Before Android P, 分身大师 hooked the ActivityThread message flow, intercepting the LAUNCH_ACTIVITY message to replace placeholder Activities with real ones. The following images compare the full message lists of Android O and Android P.

Android O message list:

Android O message list
Android O message list

Android P message list:

Android P message list
Android P message list

Comparison shows that in Android P the messages from LAUNCH_ACTIVITY to DESTROY_ACTIVITY have been removed; all Activity lifecycle handling is now performed inside the EXECUTE_TRANSACTION message.

case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    mTransactionExecutor.execute(transaction);
    if (isSystem()) {
        transaction.recycle();
    }
    break;

1.2 EXECUTE_TRANSACTION Processing

The EXECUTE_TRANSACTION message carries a ClientTransaction object, and the actual work is delegated to TransactionExecutor. Core business logic resides in ClientTransactionItem subclasses.

public void execute(ClientTransaction transaction) {
    final IBinder token = transaction.getActivityToken();
    executeCallbacks(transaction);
    executeLifecycleState(transaction);
    mPendingActions.clear();
}
public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);
    }
}

The relationship between ClientTransactionHandler and its items is illustrated below.

ClientTransactionHandler class diagram
ClientTransactionHandler class diagram

Each ClientTransactionItem implements an abstract interface that manages a specific Activity lifecycle stage. The launch flow is handled by the LaunchActivityItem subclass, whose execute method is similar to the old LAUNCH_ACTIVITY handling.

1.3 Activity Launch Sequence in Android P

Android P Activity launch flowchart
Android P Activity launch flowchart

Adapting 分身大师 for Android P

2.1 Placeholder Replacement

The launch method remains unchanged, so the strategy of swapping the real Activity with a placeholder Activity by hooking startActivity and replacing the Intent stays the same.

2.2 Placeholder Restoration

Restoring the placeholder involves replacing the placeholder Activity with the real one after the AMS message reaches the ActivityThread. In Android P, ActivityClientRecord is created inside the LaunchActivityItem.execute method rather than during the LAUNCH_ACTIVITY message.

@Override
public void execute(ClientTransactionHandler client, IBinder token,
        PendingTransactionActions pendingActions) {
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
            mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState,
            mPersistentState, mPendingResults, mPendingNewIntents, mIsForward,
            mProfilerInfo, client);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

On the AMS side, ClientTransaction is built in ActivityStackSupervisor.realStartActivityLocked and sent to the client via ClientLifeCycleManager:

final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread, r.appToken);
clientTransaction.addCallback(
    LaunchActivityItem.obtain(new Intent(r.intent),
        System.identityHashCode(r),
        r.info,
        configs.mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(),
        r.compat,
        r.launchedFromPackage,
        task.voiceInteractor,
        app.repProcState,
        r.icicle,
        r.persistentState,
        results,
        newIntents,
        mService.isNextTransitionForward(),
        profilerInfo));
if (andResume) {
    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
} else {
    lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

3. System Provider Adaptation

After Activity replacement, the app still fails because the SettingsProvider performs package‑name and UID checks during startup. In Android O, 分身大师 hooked AMS’s getProvider and replaced the mProviderMap to bypass the check. In Android P the provider is obtained earlier, before the hook, causing verification errors.

SettingsProvider classes
SettingsProvider classes

The Settings.Global class retrieves the provider via NameValueCache.getProvider:

public IContentProvider getProvider(ContentResolver contentResolver) {
    synchronized (mLock) {
        if (mContentProvider == null) {
            mContentProvider = contentResolver.acquireProvider(mUri.getAuthority());
        }
        return mContentProvider;
    }
}

Clearing the cached IContentProvider in ContentProviderHolder forces a re‑acquisition after the hook is in place, allowing the substituted provider to be used.

Conclusion

Android P refactors the framework layer, using ClientTransactionHandler to manage ClientTransactionItem and control the Activity lifecycle.

SettingsProvider is fetched earlier; to replace it via Binder hook, the previously obtained IContentProvider must be cleared.

With these adaptations, 分身大师 now supports dual‑open for WeChat, QQ and other major apps on Android P, with more apps in progress.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

mobile developmentAndroidHookAndroid PActivity Lifecycle
Qizhuo Club
Written by

Qizhuo Club

360 Mobile tech channel sharing practical experience and original insights from 360 Mobile Security and other teams across Android, iOS, big data, AI, and more.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.