Do not override finish activity behavior on back event
... if the activity was not started from Launcher. The launcher activity was started from notification and was not removed while swiping back. Another activity instance was added on top of the same task when the app was started from Launcher because the intent that started the task and the intent that started from Launcher are different. Also adding unit test to verify task is moved to back if the root activity was started from Launcher. Bug: 272723475 Test: atest ActivityRecordTests Change-Id: I97ccce3a7491669ab6b649b6e1f053beae3828f0
This commit is contained in:
@@ -78,8 +78,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
@@ -1645,18 +1643,15 @@ class ActivityClientController extends IActivityClientController.Stub {
|
||||
launchedFromHome = root.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME);
|
||||
}
|
||||
|
||||
// If the activity is one of the main entry points for the application, then we should
|
||||
// If the activity was launched directly from the home screen, then we should
|
||||
// refrain from finishing the activity and instead move it to the back to keep it in
|
||||
// memory. The requirements for this are:
|
||||
// 1. The activity is the last running activity in the task.
|
||||
// 2. The current activity is the base activity for the task.
|
||||
// 3. a. If the activity was launched by the home process, we trust that its intent
|
||||
// was resolved, so we check if the it is a main intent for the application.
|
||||
// b. Otherwise, we query Package Manager to verify whether the activity is a
|
||||
// launcher activity for the application.
|
||||
// 3. The activity was launched by the home process, and is one of the main entry
|
||||
// points for the application.
|
||||
if (baseActivityIntent != null && isLastRunningActivity
|
||||
&& ((launchedFromHome && ActivityRecord.isMainIntent(baseActivityIntent))
|
||||
|| isLauncherActivity(baseActivityIntent.getComponent()))) {
|
||||
&& launchedFromHome && ActivityRecord.isMainIntent(baseActivityIntent)) {
|
||||
moveActivityTaskToBack(token, true /* nonRoot */);
|
||||
return;
|
||||
}
|
||||
@@ -1668,31 +1663,6 @@ class ActivityClientController extends IActivityClientController.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries PackageManager to see if the given activity is one of the main entry point for the
|
||||
* application. This should not be called with the WM lock held.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean isLauncherActivity(@NonNull ComponentName activity) {
|
||||
final Intent queryIntent = new Intent(Intent.ACTION_MAIN);
|
||||
queryIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
queryIntent.setPackage(activity.getPackageName());
|
||||
try {
|
||||
final ParceledListSlice<ResolveInfo> resolved =
|
||||
mService.getPackageManager().queryIntentActivities(
|
||||
queryIntent, null, 0, mContext.getUserId());
|
||||
if (resolved == null) return false;
|
||||
for (final ResolveInfo ri : resolved.getList()) {
|
||||
if (ri.getComponentInfo().getComponentName().equals(activity)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to query intent activities", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableTaskLocaleOverride(IBinder token) {
|
||||
if (UserHandle.getAppId(Binder.getCallingUid()) != SYSTEM_UID) {
|
||||
|
||||
@@ -83,6 +83,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_CANCELLED;
|
||||
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
|
||||
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REQUESTED;
|
||||
import static com.android.server.wm.ActivityRecord.LAUNCH_SOURCE_TYPE_HOME;
|
||||
import static com.android.server.wm.ActivityRecord.State.DESTROYED;
|
||||
import static com.android.server.wm.ActivityRecord.State.DESTROYING;
|
||||
import static com.android.server.wm.ActivityRecord.State.FINISHING;
|
||||
@@ -3682,6 +3683,23 @@ public class ActivityRecordTests extends WindowTestsBase {
|
||||
assertTrue(activity.inTransition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the task is moved to back when back pressed if the root activity was originally
|
||||
* started from Launcher.
|
||||
*/
|
||||
@Test
|
||||
public void testMoveTaskToBackWhenStartedFromLauncher() {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final ActivityRecord ar = createActivityRecord(task);
|
||||
task.realActivity = ar.mActivityComponent;
|
||||
ar.intent.setAction(Intent.ACTION_MAIN);
|
||||
ar.intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
doReturn(true).when(ar).isLaunchSourceType(eq(LAUNCH_SOURCE_TYPE_HOME));
|
||||
|
||||
mAtm.mActivityClientController.onBackPressed(ar.token, null /* callback */);
|
||||
verify(task).moveTaskToBack(any());
|
||||
}
|
||||
|
||||
private ICompatCameraControlCallback getCompatCameraControlCallback() {
|
||||
return new ICompatCameraControlCallback.Stub() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user