---- launcher端 ----
07-30 16:17:27.140 1333 1333 D xmsysui : startTasks
07-30 16:17:27.140 1333 1333 D xmsysui : java.lang.Exception
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.quickstep.SystemUiProxy.startTasks(SystemUiProxy.java:1012)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.quickstep.util.SplitSelectStateController.launchTasks(SplitSelectStateController.java:462)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.quickstep.util.SplitSelectStateController.launchSplitTasks(SplitSelectStateController.java:351)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.quickstep.util.SplitSelectStateController.launchSplitTasks(SplitSelectStateController.java:371)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.quickstep.views.RecentsView.lambda$confirmSplitSelect$45(RecentsView.java:5348)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.quickstep.views.RecentsView.$r8$lambda$Z4VyoYJdEinFf5QssVYcQ-J5348(RecentsView.java:0)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.quickstep.views.RecentsView$$ExternalSyntheticLambda8.accept(R8$$SyntheticClass:0)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.launcher3.anim.AnimatorListeners$EndStateCallbackWrapper.onAnimationEnd(AnimatorListeners.java:80)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.Animator$AnimatorListener.onAnimationEnd(Animator.java:755)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.Animator$AnimatorCaller$$ExternalSyntheticLambda1.call(D8$$SyntheticClass:0)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.Animator.callOnList(Animator.java:713)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.Animator.notifyListeners(Animator.java:634)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.Animator.notifyEndListeners(Animator.java:659)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.Animator.completeEndAnimation(Animator.java:679)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.ValueAnimator.completeEndAnimation(ValueAnimator.java:1321)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.Animator.notifyEndListenersFromEndAnimation(Animator.java:668)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1312)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1577)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.ValueAnimator.pulseAnimationFrame(ValueAnimator.java:1593)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.AnimatorSet.pulseFrame(AnimatorSet.java:1314)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.AnimatorSet.handleAnimationEvents(AnimatorSet.java:1297)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.AnimatorSet.doAnimationFrame(AnimatorSet.java:1197)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:396)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame(Unknown Source:0)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:106)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1564)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1575)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.view.Choreographer.doCallbacks(Choreographer.java:1175)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.view.Choreographer.doFrame(Choreographer.java:1100)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1549)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.os.Handler.handleCallback(Handler.java:991)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.os.Handler.dispatchMessage(Handler.java:102)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.os.Looper.loopOnce(Looper.java:232)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.os.Looper.loop(Looper.java:317)
07-30 16:17:27.140 1333 1333 D xmsysui : at android.app.ActivityThread.main(ActivityThread.java:8934)
07-30 16:17:27.140 1333 1333 D xmsysui : at java.lang.reflect.Method.invoke(Native Method)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:591)
07-30 16:17:27.140 1333 1333 D xmsysui : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
---- systemui端 ------
07-30 16:17:27.142 977 1522 D xmsysui : startTasks 1251
07-30 16:17:27.142 977 1522 D xmsysui : java.lang.Exception
07-30 16:17:27.142 977 1522 D xmsysui : at com.android.wm.shell.splitscreen.SplitScreenController$ISplitScreenImpl.startTasks(SplitScreenController.java:1251)
07-30 16:17:27.142 977 1522 D xmsysui : at com.android.wm.shell.splitscreen.ISplitScreen$Stub.onTransact(ISplitScreen.java:235)
07-30 16:17:27.142 977 1522 D xmsysui : at android.os.Binder.execTransactInternal(Binder.java:1411)
07-30 16:17:27.142 977 1522 D xmsysui : at android.os.Binder.execTransact(Binder.java:1350)
这里面涉及launcher3和systemui两个进程。
launcher3端流程
public void startTasks(int taskId1, Bundle options1, int taskId2, Bundle options2,
@StagePosition int splitPosition, @PersistentSnapPosition int snapPosition,
RemoteTransition remoteTransition, InstanceId instanceId) {
if (mSystemUiProxy != null) {
try {
//调用aidl方法
mSplitScreen.startTasks(taskId1, options1, taskId2, options2, splitPosition,
snapPosition, remoteTransition, instanceId);
} catch (RemoteException e) {
Log.w(TAG, splitFailureMessage("startTasks", "RemoteException"), e);
}
}
}
调用mSplitScreen的aidl方法,这个binder对象是哪里赋值的?源码查找发现是在launcher3里面packages/apps/Launcher3/quickstep/src/com/android/quickstep/TouchInteractionService.java中赋值的。
@BinderThread
public void onInitialize(Bundle bundle) {
ISystemUiProxy proxy = ISystemUiProxy.Stub.asInterface(
bundle.getBinder(ISystemUiProxy.DESCRIPTOR));
// 这个看上去像是app右上角的数量角标
IBubbles bubbles = IBubbles.Stub.asInterface(bundle.getBinder(IBubbles.DESCRIPTOR));
// 这个就是分屏的binder
ISplitScreen splitscreen = ISplitScreen.Stub.asInterface(bundle.getBinder(
ISplitScreen.DESCRIPTOR));
MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
// 赋值给SystemUiProxy
SystemUiProxy.INSTANCE.get(tis).setProxy(proxy, pip,
bubbles, splitscreen, onehanded, shellTransitions, startingWindow,
recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode,
unfoldTransition, dragAndDrop);
tis.initInputMonitor("TISBinder#onInitialize()");
tis.preloadOverview(true /* fromInit */);
}));
sIsInitialized = true;
}
那onInitialize是哪里调用的? 是在systemui里面绑定这个service并传递binder对象给launcher,launcher后面就可以跨进程通信了。
systemui端流程
packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
private void maybeBindService() {
try {
// 绑定service mQuickStepIntent = new Intent("android.intent.action.QUICKSTEP_SERVICE")
mBound = mContext.bindServiceAsUser(mQuickStepIntent,
mOverviewServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
currentUser);
} catch (SecurityException e) {
Log.e(TAG_OPS, "Unable to bind because of security error", e);
}
if (mBound) {
mIsPrevServiceCleanedUp = false;
// Ensure that connection has been established even if it thinks it is bound
mHandler.postDelayed(mDeferredConnectionCallback, DEFERRED_CALLBACK_MILLIS);
} else {
// Retry after exponential backoff timeout
retryConnectionWithBackoff();
}
}
绑定的service的action是"android.intent.action.QUICKSTEP_SERVICE",源码查找一下是在launcher3里面manifest
packages/apps/Launcher3/quickstep/AndroidManifest.xml
<service android:name="com.android.quickstep.TouchInteractionService"
android:permission="android.permission.STATUS_BAR_SERVICE"
android:directBootAware="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.QUICKSTEP_SERVICE"/>
</intent-filter>
</service>
bindServiceAsUser传的connection对象
private final ServiceConnection mOverviewServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mCurrentBoundedUserId = mUserTracker.getUserId();
mOverviewProxy = IOverviewProxy.Stub.asInterface(service);
// new了一个bundle对象,用于添加binder对象返回给launcher端的service
Bundle params = new Bundle();
addInterface(mSysUiProxy, params);
addInterface(mSysuiUnlockAnimationController, params);
addInterface(mUnfoldTransitionProgressForwarder.orElse(null), params);
// Add all the interfaces exposed by the shell
// 这里面添加ISplitScreen.Stub对象
mShellInterface.createExternalInterfaces(params);
try {
// 调用launcher端service的onInitialize,解了上面的疑问
mOverviewProxy.onInitialize(params);
} catch (RemoteException e) {
mCurrentBoundedUserId = -1;
Log.e(TAG_OPS, "Failed to call onInitialize()", e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.w(TAG_OPS, "Service disconnected");
// Do nothing
mCurrentBoundedUserId = -1;
}
};
连接到launcher端的service后,调用service的onInitialize方法,并传了很多的binder对象过去,用于后面的跨进程通信,这里面就包含了ISplitScreen对象