Mobile Development 11 min read

Adapting the Dual‑Instance Plugin Framework to Android P Activity Lifecycle Changes

This article explains how the highly invasive plugin framework "Dual Master" is adapted to Android P by analyzing the refactored Activity lifecycle handling, the EXECUTE_TRANSACTION message flow, and the necessary code modifications for activity placeholder replacement, restoration, and system provider hooking.

360 Tech Engineering
360 Tech Engineering
360 Tech Engineering
Adapting the Dual‑Instance Plugin Framework to Android P Activity Lifecycle Changes

The "Dual Master" plugin framework heavily hooks the Android framework to run duplicated applications, but Android P restructures the framework layer, especially the Activity lifecycle, requiring a series of adaptations.

1. Android P Activity Lifecycle Changes

In Android O, the framework intercepts the LAUNCH_ACTIVITY message in ActivityThread to replace placeholder activities with real ones. Android P removes the entire range of messages from LAUNCH_ACTIVITY to DESTROY_ACTIVITY , consolidating lifecycle handling into the EXECUTE_TRANSACTION message.

The handling code for EXECUTE_TRANSACTION is:

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

1.2 EXECUTE_TRANSACTION Processing Flow

The ClientTransaction carries a list of ClientTransactionItem objects, which are executed by TransactionExecutor :

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();
final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
ClientTransactionItem item = callbacks.get(i);
item.execute(mTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
}
}

The relationship diagram (ClientTransactionHandler hierarchy) is shown below:

Activity launch is performed by the LaunchActivityItem subclass:

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

The server side (AMS) creates the ClientTransaction and sends it 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);
}

2. Adapting Dual Master Activities

2.1 Placeholder Replacement – the original strategy of swapping the Intent at startActivity remains unchanged.

2.2 Placeholder Restoration – after the ActivityThread receives the message from AMS, the placeholder must be swapped back to the real Activity. In Android P the ActivityClientRecord is created inside LaunchActivityItem.execute , so the replacement must modify the fields of the LaunchActivityItem instance:

ArrayList<Object> mActivityCallbacks = ClientTransaction.mActivityCallbacks.get(msg.obj);
for (int i=0; i<mActivityCallbacks.size(); i++) {
Object obj = mActivityCallbacks.get(i);
if (obj.getClass().equals(LaunchActivityItem.Class)) {
Object launchActivityItem = obj;
try {
Class cls_launch = Class.forName("android.app.servertransaction.LaunchActivityItem");
Field field_mInfo = cls_launch.getDeclaredField("mInfo");
field_mInfo.setAccessible(true);
Field field_mIntent = cls_launch.getDeclaredField("mIntent");
field_mIntent.setAccessible(true);
field_mInfo.set(launchActivityItem, targetActivityInfo);
field_mIntent.set(launchActivityItem, targetIntent);
} catch (Exception e) { e.printStackTrace(); }
}
}

In Android O the LAUNCH_ACTIVITY message could be intercepted directly, but in Android P the ActivityClientRecord is built later, so the above reflective modification is required.

3. System Provider Adaptation

After activity replacement, the app may still crash because the SettingsProvider validates package name and UID. In Android P the provider is obtained earlier, before the hook can replace it. The relevant code in Settings.Global is:

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

By clearing the previously cached ContentProviderHolder.mContentProvider after hooking getProvider and the mProviderMap , the system will re‑acquire the provider, allowing the hooked version to be used.

4. Summary

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

The SettingsProvider is fetched earlier; to hook it successfully, the cached provider must be cleared before use.

With these adaptations, Dual Master now supports dual‑instance launching on Android P for popular apps such as WeChat and QQ, and further apps are being integrated.

AndroidHookingPlugin FrameworkAndroid PActivity LifecycleSystem Provider
360 Tech Engineering
Written by

360 Tech Engineering

Official tech channel of 360, building the most professional technology aggregation platform for the brand.

0 followers
Reader feedback

How this landed with the community

login 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.