diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index 01dfb91d12be6..9bf69bcc2eaab 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -387,11 +387,16 @@ public abstract class ActivityTaskManagerInternal { public abstract ComponentName getActivityName(IBinder activityToken); /** - * @return the activity token and IApplicationThread for the top activity in the task or null - * if there isn't a top activity with a valid process. + * Returns non-finishing Activity that have a process attached for the given task and the token + * with the activity token and the IApplicationThread or null if there is no Activity with a + * valid process. Given the null token for the task will return the top Activity in the task. + * + * @param taskId the Activity task id. + * @param token the Activity token, set null if get top Activity for the given task id. */ @Nullable - public abstract ActivityTokens getTopActivityForTask(int taskId); + public abstract ActivityTokens getAttachedNonFinishingActivityForTask(int taskId, + IBinder token); public abstract IIntentSender getIntentSender(int type, String packageName, @Nullable String featureId, int callingUid, int userId, IBinder token, String resultWho, diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 14436bc4ed669..1f7c0efa572ee 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -2944,7 +2944,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final long callingId = Binder.clearCallingIdentity(); LocalService.ActivityTokens tokens = null; try { - tokens = mInternal.getTopActivityForTask(taskId); + tokens = mInternal.getAttachedNonFinishingActivityForTask(taskId, null); } finally { Binder.restoreCallingIdentity(callingId); } @@ -5804,7 +5804,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public ActivityTokens getTopActivityForTask(int taskId) { + public ActivityTokens getAttachedNonFinishingActivityForTask(int taskId, + IBinder token) { synchronized (mGlobalLock) { final Task task = mRootWindowContainer.anyTaskForId(taskId, MATCH_ATTACHED_TASK_ONLY); @@ -5813,19 +5814,30 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { + " Requested task not found"); return null; } - final ActivityRecord activity = task.getTopNonFinishingActivity(); - if (activity == null) { - Slog.w(TAG, "getApplicationThreadForTopActivity failed:" - + " Requested activity not found"); + final List list = new ArrayList<>(); + task.forAllActivities(r -> { + if (!r.finishing) { + list.add(r); + } + }); + if (list.size() <= 0) { return null; } - if (!activity.attachedToProcess()) { - Slog.w(TAG, "getApplicationThreadForTopActivity failed: No process for " - + activity); - return null; + // pass null, get top Activity + if (token == null && list.get(0).attachedToProcess()) { + ActivityRecord topRecord = list.get(0); + return new ActivityTokens(topRecord.token, topRecord.assistToken, + topRecord.app.getThread(), topRecord.shareableActivityToken); } - return new ActivityTokens(activity.token, activity.assistToken, - activity.app.getThread(), activity.shareableActivityToken); + // find the expected Activity + for (int i = 0; i < list.size(); i++) { + ActivityRecord record = list.get(i); + if (record.shareableActivityToken == token && record.attachedToProcess()) { + return new ActivityTokens(record.token, record.assistToken, + record.app.getThread(), record.shareableActivityToken); + } + } + return null; } } diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java index d3a589668808e..97d5215213a9a 100644 --- a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java +++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java @@ -232,23 +232,26 @@ final class TranslationManagerServiceImpl extends public void updateUiTranslationStateLocked(@UiTranslationState int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, List viewIds, IBinder token, int taskId, UiTranslationSpec uiTranslationSpec) { - // Get top activity for a given task id - final ActivityTokens taskTopActivityTokens = - mActivityTaskManagerInternal.getTopActivityForTask(taskId); - if (taskTopActivityTokens == null - || taskTopActivityTokens.getShareableActivityToken() != token) { - Slog.w(TAG, "Unknown activity or it was finished to query for update translation " - + "state for token=" + token + " taskId=" + taskId + " for state= " + state); + // If the app starts a new Activity in the same task then the finish or pause API + // is called, the operation doesn't work if we only check task top Activity. The top + // Activity is the new Activity, the original Activity is paused in the same task. + // To make sure the operation still work, we use the token to find the target Activity in + // this task, not the top Activity only. + ActivityTokens candidateActivityTokens = + mActivityTaskManagerInternal.getAttachedNonFinishingActivityForTask(taskId, token); + if (candidateActivityTokens == null) { + Slog.w(TAG, "Unknown activity or it was finished to query for update " + + "translation state for token=" + token + " taskId=" + taskId + " for " + + "state= " + state); return; } - mLastActivityTokens = new WeakReference<>(taskTopActivityTokens); + mLastActivityTokens = new WeakReference<>(candidateActivityTokens); if (state == STATE_UI_TRANSLATION_FINISHED) { mWaitingFinishedCallbackActivities.add(token); } - - IBinder activityToken = taskTopActivityTokens.getActivityToken(); + IBinder activityToken = candidateActivityTokens.getActivityToken(); try { - taskTopActivityTokens.getApplicationThread().updateUiTranslationState( + candidateActivityTokens.getApplicationThread().updateUiTranslationState( activityToken, state, sourceSpec, targetSpec, viewIds, uiTranslationSpec); } catch (RemoteException e) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index 0519873810b54..edf1002221ba9 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -311,8 +311,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne callback.sendResult(null); return; } - final ActivityTokens tokens = LocalServices.getService( - ActivityTaskManagerInternal.class).getTopActivityForTask(taskId); + final ActivityTokens tokens = LocalServices.getService(ActivityTaskManagerInternal.class) + .getAttachedNonFinishingActivityForTask(taskId, null); if (tokens == null || tokens.getAssistToken() != assistToken) { Slog.w(TAG, "Unknown activity to query for direct actions"); callback.sendResult(null); @@ -336,8 +336,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne resultCallback.sendResult(null); return; } - final ActivityTokens tokens = LocalServices.getService( - ActivityTaskManagerInternal.class).getTopActivityForTask(taskId); + final ActivityTokens tokens = LocalServices.getService(ActivityTaskManagerInternal.class) + .getAttachedNonFinishingActivityForTask(taskId, null); if (tokens == null || tokens.getAssistToken() != assistToken) { Slog.w(TAG, "Unknown activity to perform a direct action"); resultCallback.sendResult(null);