Loading core/java/android/app/ActivityThread.java +56 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ import static com.android.internal.os.SafeZipPathValidatorCallback.VALIDATE_ZIP_ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions.SceneTransitionInfo; import android.app.HandoffActivityData; import android.app.HandoffActivityDataRequestInfo; import android.app.RemoteServiceException.BadForegroundServiceNotificationException; import android.app.RemoteServiceException.BadUserInitiatedJobNotificationException; import android.app.RemoteServiceException.CannotPostForegroundServiceNotificationException; Loading Loading @@ -1129,6 +1131,11 @@ public final class ActivityThread extends ClientTransactionHandler int flags; } static final class RequestHandoffActivityData { List<IBinder> activityTokens; IBinder requestToken; } // A list of receivers and an index into the receiver to be processed next. static final class ReceiverList { List<ReceiverInfo> receivers; Loading Loading @@ -2116,6 +2123,21 @@ public final class ActivityThread extends ClientTransactionHandler sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd); } /** * Requests the data needed to start a handoff activity. * * @param requestToken The token of the request, used by ActivityTaskManager to identify * the request. * @param activityTokens The tokens of the activities to hand off. */ @Override public void requestHandoffActivityData(IBinder requestToken, List<IBinder> activityTokens) { RequestHandoffActivityData cmd = new RequestHandoffActivityData(); cmd.activityTokens = activityTokens; cmd.requestToken = requestToken; sendMessage(H.REQUEST_HANDOFF_ACTIVITY_DATA, cmd); } @Override public void setCoreSettings(Bundle coreSettings) { sendMessage(H.SET_CORE_SETTINGS, coreSettings); Loading Loading @@ -2513,6 +2535,7 @@ public final class ActivityThread extends ClientTransactionHandler public static final int FINISH_INSTRUMENTATION_WITHOUT_RESTART = 171; public static final int TIMEOUT_SERVICE_FOR_TYPE = 172; public static final int REQUEST_HANDOFF_ACTIVITY_DATA = 173; String codeToString(int code) { if (DEBUG_MESSAGES) { Loading Loading @@ -2568,6 +2591,7 @@ public final class ActivityThread extends ClientTransactionHandler case TIMEOUT_SERVICE: return "TIMEOUT_SERVICE"; case PING: return "PING"; case TIMEOUT_SERVICE_FOR_TYPE: return "TIMEOUT_SERVICE_FOR_TYPE"; case REQUEST_HANDOFF_ACTIVITY_DATA: return "REQUEST_HANDOFF_ACTIVITY_DATA"; } } return Integer.toString(code); Loading Loading @@ -2889,6 +2913,12 @@ public final class ActivityThread extends ClientTransactionHandler case FINISH_INSTRUMENTATION_WITHOUT_RESTART: handleFinishInstrumentationWithoutRestart(); break; case REQUEST_HANDOFF_ACTIVITY_DATA: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "handleHandoffActivityDataRequest"); handleHandoffActivityDataRequest((RequestHandoffActivityData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } long messageElapsedTimeMs = SystemClock.uptimeMillis() - messageStartUptimeMs; Object obj = msg.obj; Loading Loading @@ -4606,6 +4636,32 @@ public final class ActivityThread extends ClientTransactionHandler deliverNewIntents(r, intents); } private void handleHandoffActivityDataRequest(RequestHandoffActivityData cmd) { final HandoffActivityDataRequestInfo requestInfo = new HandoffActivityDataRequestInfo(true); final List<HandoffActivityData> handoffActivityData = new ArrayList<>(); for (IBinder activityToken : cmd.activityTokens) { final ActivityClientRecord r = mActivities.get(activityToken); if (r != null) { final HandoffActivityData dataForActivity = r.activity.onHandoffActivityDataRequested(requestInfo); if (dataForActivity == null) { Log.w(TAG, "HandoffActivityData is null for " + r.activity.getComponentName()); } handoffActivityData.add(dataForActivity); } else { Log.w(TAG, "Attempted to fetch HandoffActivityData for non-existent activity."); handoffActivityData.add(null); } } IActivityTaskManager mgr = ActivityTaskManager.getService(); try { mgr.reportHandoffActivityData(cmd.requestToken, handoffActivityData); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) { // Filling for autofill has a few differences: // - it does not need an AssistContent Loading core/java/android/app/HandoffFailureCode.java 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import android.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Defines failure codes for handoff task data requests. * @hide */ public final class HandoffFailureCode { private HandoffFailureCode() {} /** @hide */ @IntDef(prefix = { "HANDOFF_FAILURE_" }, value = { HANDOFF_FAILURE_TIMEOUT, HANDOFF_FAILURE_UNSUPPORTED_DEVICE, HANDOFF_FAILURE_UNKNOWN_TASK, HANDOFF_FAILURE_INTERNAL_ERROR, HANDOFF_FAILURE_EMPTY_TASK, HANDOFF_FAILURE_UNSUPPORTED_TASK }) @Retention(RetentionPolicy.SOURCE) public @interface FailureCode {} /** The handoff task data request timed out. */ public static final int HANDOFF_FAILURE_TIMEOUT = 1; /** The device does not support handoff. */ public static final int HANDOFF_FAILURE_UNSUPPORTED_DEVICE = 2; /** The handoff task data request was a task that no longer exists. */ public static final int HANDOFF_FAILURE_UNKNOWN_TASK = 3; /** An internal error occurred while handling the handoff task data request. For example, * the app process died during a handoff request. */ public static final int HANDOFF_FAILURE_INTERNAL_ERROR = 4; /** The handoff task data request was for an empty task. */ public static final int HANDOFF_FAILURE_EMPTY_TASK = 5; /** The handoff task data request was for a task whose top activity does not support handoff. */ public static final int HANDOFF_FAILURE_UNSUPPORTED_TASK = 6; } No newline at end of file core/java/android/app/IActivityTaskManager.aidl +13 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.ActivityTaskManager; import android.app.ApplicationErrorReport; import android.app.ContentProviderHolder; import android.app.GrantedUriPermission; import android.app.HandoffActivityData; import android.app.IApplicationThread; import android.app.IActivityClientController; import android.app.IActivityController; Loading Loading @@ -426,4 +427,16 @@ interface IActivityTaskManager { * @hide */ void moveRootTaskToDisplayOnTopOrBottom(int taskId, int displayId, boolean onTop); /** * Reports HandoffActivityData for a given set of activities back to * ActivityTaskManager. * * @param requestToken A request token used by ActivityTaskManager to * identify the request. * @param data A list of HandoffActivityData objects containing the data for the requested * activities in the same order as the request. * @hide */ void reportHandoffActivityData(in IBinder requestToken, in List<HandoffActivityData> data); } core/java/android/app/IApplicationThread.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.app; import android.app.ActivityOptions.SceneTransitionInfo; import android.app.ContentProviderHolder; import android.app.HandoffActivityData; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; Loading Loading @@ -188,4 +189,5 @@ oneway interface IApplicationThread { void schedulePing(in RemoteCallback pong); void getExecutableMethodFileOffsets(in MethodDescriptor methodDescriptor, in IOffsetCallback resultCallback); void requestHandoffActivityData(in IBinder requestToken, in List<IBinder> activityTokens); } core/java/android/app/IHandoffTaskDataReceiver.aidl 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import android.app.HandoffActivityData; /** @hide */ oneway interface IHandoffTaskDataReceiver { /* * Called when the handoff task data request has succeeded. * * @param taskId The id of the task that the request was made for. * @param handoffActivityData A list of {@link HandoffActivityData} for this * task, retaining the order of the activities in the task with the topmost * activity at index 0. If the topmost activity of the task did not return * any HandoffActivityData, this list will be empty. */ void onHandoffTaskDataRequestSucceeded( in int taskId, in List<HandoffActivityData> handoffActivityData); /* * Called when the handoff task data request has failed. * * @param taskId The id of the task that the request was made for. * @param resultCode The result code of the failure, represented as an {@link HandoffFailureCode} */ void onHandoffTaskDataRequestFailed(in int taskId, in int resultCode); } Loading
core/java/android/app/ActivityThread.java +56 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ import static com.android.internal.os.SafeZipPathValidatorCallback.VALIDATE_ZIP_ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions.SceneTransitionInfo; import android.app.HandoffActivityData; import android.app.HandoffActivityDataRequestInfo; import android.app.RemoteServiceException.BadForegroundServiceNotificationException; import android.app.RemoteServiceException.BadUserInitiatedJobNotificationException; import android.app.RemoteServiceException.CannotPostForegroundServiceNotificationException; Loading Loading @@ -1129,6 +1131,11 @@ public final class ActivityThread extends ClientTransactionHandler int flags; } static final class RequestHandoffActivityData { List<IBinder> activityTokens; IBinder requestToken; } // A list of receivers and an index into the receiver to be processed next. static final class ReceiverList { List<ReceiverInfo> receivers; Loading Loading @@ -2116,6 +2123,21 @@ public final class ActivityThread extends ClientTransactionHandler sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd); } /** * Requests the data needed to start a handoff activity. * * @param requestToken The token of the request, used by ActivityTaskManager to identify * the request. * @param activityTokens The tokens of the activities to hand off. */ @Override public void requestHandoffActivityData(IBinder requestToken, List<IBinder> activityTokens) { RequestHandoffActivityData cmd = new RequestHandoffActivityData(); cmd.activityTokens = activityTokens; cmd.requestToken = requestToken; sendMessage(H.REQUEST_HANDOFF_ACTIVITY_DATA, cmd); } @Override public void setCoreSettings(Bundle coreSettings) { sendMessage(H.SET_CORE_SETTINGS, coreSettings); Loading Loading @@ -2513,6 +2535,7 @@ public final class ActivityThread extends ClientTransactionHandler public static final int FINISH_INSTRUMENTATION_WITHOUT_RESTART = 171; public static final int TIMEOUT_SERVICE_FOR_TYPE = 172; public static final int REQUEST_HANDOFF_ACTIVITY_DATA = 173; String codeToString(int code) { if (DEBUG_MESSAGES) { Loading Loading @@ -2568,6 +2591,7 @@ public final class ActivityThread extends ClientTransactionHandler case TIMEOUT_SERVICE: return "TIMEOUT_SERVICE"; case PING: return "PING"; case TIMEOUT_SERVICE_FOR_TYPE: return "TIMEOUT_SERVICE_FOR_TYPE"; case REQUEST_HANDOFF_ACTIVITY_DATA: return "REQUEST_HANDOFF_ACTIVITY_DATA"; } } return Integer.toString(code); Loading Loading @@ -2889,6 +2913,12 @@ public final class ActivityThread extends ClientTransactionHandler case FINISH_INSTRUMENTATION_WITHOUT_RESTART: handleFinishInstrumentationWithoutRestart(); break; case REQUEST_HANDOFF_ACTIVITY_DATA: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "handleHandoffActivityDataRequest"); handleHandoffActivityDataRequest((RequestHandoffActivityData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } long messageElapsedTimeMs = SystemClock.uptimeMillis() - messageStartUptimeMs; Object obj = msg.obj; Loading Loading @@ -4606,6 +4636,32 @@ public final class ActivityThread extends ClientTransactionHandler deliverNewIntents(r, intents); } private void handleHandoffActivityDataRequest(RequestHandoffActivityData cmd) { final HandoffActivityDataRequestInfo requestInfo = new HandoffActivityDataRequestInfo(true); final List<HandoffActivityData> handoffActivityData = new ArrayList<>(); for (IBinder activityToken : cmd.activityTokens) { final ActivityClientRecord r = mActivities.get(activityToken); if (r != null) { final HandoffActivityData dataForActivity = r.activity.onHandoffActivityDataRequested(requestInfo); if (dataForActivity == null) { Log.w(TAG, "HandoffActivityData is null for " + r.activity.getComponentName()); } handoffActivityData.add(dataForActivity); } else { Log.w(TAG, "Attempted to fetch HandoffActivityData for non-existent activity."); handoffActivityData.add(null); } } IActivityTaskManager mgr = ActivityTaskManager.getService(); try { mgr.reportHandoffActivityData(cmd.requestToken, handoffActivityData); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) { // Filling for autofill has a few differences: // - it does not need an AssistContent Loading
core/java/android/app/HandoffFailureCode.java 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import android.annotation.IntDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Defines failure codes for handoff task data requests. * @hide */ public final class HandoffFailureCode { private HandoffFailureCode() {} /** @hide */ @IntDef(prefix = { "HANDOFF_FAILURE_" }, value = { HANDOFF_FAILURE_TIMEOUT, HANDOFF_FAILURE_UNSUPPORTED_DEVICE, HANDOFF_FAILURE_UNKNOWN_TASK, HANDOFF_FAILURE_INTERNAL_ERROR, HANDOFF_FAILURE_EMPTY_TASK, HANDOFF_FAILURE_UNSUPPORTED_TASK }) @Retention(RetentionPolicy.SOURCE) public @interface FailureCode {} /** The handoff task data request timed out. */ public static final int HANDOFF_FAILURE_TIMEOUT = 1; /** The device does not support handoff. */ public static final int HANDOFF_FAILURE_UNSUPPORTED_DEVICE = 2; /** The handoff task data request was a task that no longer exists. */ public static final int HANDOFF_FAILURE_UNKNOWN_TASK = 3; /** An internal error occurred while handling the handoff task data request. For example, * the app process died during a handoff request. */ public static final int HANDOFF_FAILURE_INTERNAL_ERROR = 4; /** The handoff task data request was for an empty task. */ public static final int HANDOFF_FAILURE_EMPTY_TASK = 5; /** The handoff task data request was for a task whose top activity does not support handoff. */ public static final int HANDOFF_FAILURE_UNSUPPORTED_TASK = 6; } No newline at end of file
core/java/android/app/IActivityTaskManager.aidl +13 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.ActivityTaskManager; import android.app.ApplicationErrorReport; import android.app.ContentProviderHolder; import android.app.GrantedUriPermission; import android.app.HandoffActivityData; import android.app.IApplicationThread; import android.app.IActivityClientController; import android.app.IActivityController; Loading Loading @@ -426,4 +427,16 @@ interface IActivityTaskManager { * @hide */ void moveRootTaskToDisplayOnTopOrBottom(int taskId, int displayId, boolean onTop); /** * Reports HandoffActivityData for a given set of activities back to * ActivityTaskManager. * * @param requestToken A request token used by ActivityTaskManager to * identify the request. * @param data A list of HandoffActivityData objects containing the data for the requested * activities in the same order as the request. * @hide */ void reportHandoffActivityData(in IBinder requestToken, in List<HandoffActivityData> data); }
core/java/android/app/IApplicationThread.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.app; import android.app.ActivityOptions.SceneTransitionInfo; import android.app.ContentProviderHolder; import android.app.HandoffActivityData; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; Loading Loading @@ -188,4 +189,5 @@ oneway interface IApplicationThread { void schedulePing(in RemoteCallback pong); void getExecutableMethodFileOffsets(in MethodDescriptor methodDescriptor, in IOffsetCallback resultCallback); void requestHandoffActivityData(in IBinder requestToken, in List<IBinder> activityTokens); }
core/java/android/app/IHandoffTaskDataReceiver.aidl 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import android.app.HandoffActivityData; /** @hide */ oneway interface IHandoffTaskDataReceiver { /* * Called when the handoff task data request has succeeded. * * @param taskId The id of the task that the request was made for. * @param handoffActivityData A list of {@link HandoffActivityData} for this * task, retaining the order of the activities in the task with the topmost * activity at index 0. If the topmost activity of the task did not return * any HandoffActivityData, this list will be empty. */ void onHandoffTaskDataRequestSucceeded( in int taskId, in List<HandoffActivityData> handoffActivityData); /* * Called when the handoff task data request has failed. * * @param taskId The id of the task that the request was made for. * @param resultCode The result code of the failure, represented as an {@link HandoffFailureCode} */ void onHandoffTaskDataRequestFailed(in int taskId, in int resultCode); }