Loading core/res/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -3902,6 +3902,10 @@ {@see android.view.Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS} --> <string name="config_secondaryHomeComponent" translatable="false">com.android.launcher3/com.android.launcher3.SecondaryDisplayLauncher</string> <!-- Force secondary home launcher specified in config_secondaryHomeComponent always. If this is not set, secondary home launcher can be replaced by user. --> <bool name ="config_useSystemProvidedLauncherForSecondary">false</bool> <!-- If device supports corner radius on windows. This should be turned off on low-end devices to improve animation performance. --> <bool name="config_supportsRoundedCornersOnWindows">true</bool> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3695,6 +3695,7 @@ <!-- For Secondary Launcher --> <java-symbol type="string" name="config_secondaryHomeComponent" /> <java-symbol type="bool" name="config_useSystemProvidedLauncherForSecondary" /> <java-symbol type="string" name="battery_saver_notification_channel_name" /> <java-symbol type="string" name="battery_saver_sticky_disabled_notification_title" /> Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +4 −2 Original line number Diff line number Diff line Loading @@ -5867,8 +5867,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { */ Intent getSecondaryHomeIntent(String preferredPackage) { final Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null); if (preferredPackage == null) { // Using the component stored in config if no package name. final boolean useSystemProvidedLauncher = mContext.getResources().getBoolean( com.android.internal.R.bool.config_useSystemProvidedLauncherForSecondary); if (preferredPackage == null || useSystemProvidedLauncher) { // Using the component stored in config if no package name or forced. final String secondaryHomeComponent = mContext.getResources().getString( com.android.internal.R.string.config_secondaryHomeComponent); intent.setComponent(ComponentName.unflattenFromString(secondaryHomeComponent)); Loading services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +69 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.ActivityDisplay.POSITION_TOP; Loading @@ -54,6 +55,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.util.Pair; Loading Loading @@ -600,6 +602,73 @@ public class RootActivityContainerTests extends ActivityTestsBase { assertEquals(comp.getClassName(), resolvedInfo.first.name); } /** * Tests that the default secondary home activity is always picked when it is in forced by * config_useSystemProvidedLauncherForSecondary. */ @Test public void testResolveSecondaryHomeActivityForced() throws Exception { Resources resources = mContext.getResources(); spyOn(resources); try { // setUp: set secondary launcher and force it. final String defaultSecondaryHome = "com.android.test/com.android.test.TestDefaultSecondaryHome"; final ComponentName secondaryComp = ComponentName.unflattenFromString( defaultSecondaryHome); doReturn(defaultSecondaryHome).when(resources).getString( com.android.internal.R.string.config_secondaryHomeComponent); doReturn(true).when(resources).getBoolean( com.android.internal.R.bool.config_useSystemProvidedLauncherForSecondary); final Intent secondaryHomeIntent = mService.getSecondaryHomeIntent(null); assertEquals(secondaryComp, secondaryHomeIntent.getComponent()); final ActivityInfo aInfoSecondary = new ActivityInfo(); aInfoSecondary.name = secondaryComp.getClassName(); aInfoSecondary.applicationInfo = new ApplicationInfo(); aInfoSecondary.applicationInfo.packageName = secondaryComp.getPackageName(); doReturn(aInfoSecondary).when(mRootActivityContainer).resolveHomeActivity(anyInt(), refEq(secondaryHomeIntent)); final Intent homeIntent = mService.getHomeIntent(); final ActivityInfo aInfoDefault = new ActivityInfo(); aInfoDefault.name = "fakeHomeActivity"; aInfoDefault.applicationInfo = new ApplicationInfo(); aInfoDefault.applicationInfo.packageName = "fakeHomePackage"; doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(), refEq(homeIntent)); // Let resolveActivities call to validate both main launcher and second launcher so that // resolveActivities call does not work as enabler for secondary. final List<ResolveInfo> resolutions1 = new ArrayList<>(); final ResolveInfo resolveInfo1 = new ResolveInfo(); resolveInfo1.activityInfo = new ActivityInfo(); resolveInfo1.activityInfo.name = aInfoDefault.name; resolveInfo1.activityInfo.applicationInfo = aInfoDefault.applicationInfo; resolutions1.add(resolveInfo1); doReturn(resolutions1).when(mRootActivityContainer).resolveActivities(anyInt(), refEq(homeIntent)); final List<ResolveInfo> resolutions2 = new ArrayList<>(); final ResolveInfo resolveInfo2 = new ResolveInfo(); resolveInfo2.activityInfo = new ActivityInfo(); resolveInfo2.activityInfo.name = aInfoSecondary.name; resolveInfo2.activityInfo.applicationInfo = aInfoSecondary.applicationInfo; resolutions2.add(resolveInfo2); doReturn(resolutions2).when(mRootActivityContainer).resolveActivities(anyInt(), refEq(secondaryHomeIntent)); doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay( any(), anyInt(), anyBoolean()); // Run the test final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer .resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */); assertEquals(secondaryComp.getClassName(), resolvedInfo.first.name); assertEquals(secondaryComp.getPackageName(), resolvedInfo.first.applicationInfo.packageName); assertEquals(aInfoSecondary.name, resolvedInfo.first.name); } finally { // tearDown reset(resources); } } /** * Tests that secondary home should be selected if default home not support secondary displays * or there is no matched activity in the same package as selected default home. Loading Loading
core/res/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -3902,6 +3902,10 @@ {@see android.view.Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS} --> <string name="config_secondaryHomeComponent" translatable="false">com.android.launcher3/com.android.launcher3.SecondaryDisplayLauncher</string> <!-- Force secondary home launcher specified in config_secondaryHomeComponent always. If this is not set, secondary home launcher can be replaced by user. --> <bool name ="config_useSystemProvidedLauncherForSecondary">false</bool> <!-- If device supports corner radius on windows. This should be turned off on low-end devices to improve animation performance. --> <bool name="config_supportsRoundedCornersOnWindows">true</bool> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3695,6 +3695,7 @@ <!-- For Secondary Launcher --> <java-symbol type="string" name="config_secondaryHomeComponent" /> <java-symbol type="bool" name="config_useSystemProvidedLauncherForSecondary" /> <java-symbol type="string" name="battery_saver_notification_channel_name" /> <java-symbol type="string" name="battery_saver_sticky_disabled_notification_title" /> Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +4 −2 Original line number Diff line number Diff line Loading @@ -5867,8 +5867,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { */ Intent getSecondaryHomeIntent(String preferredPackage) { final Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null); if (preferredPackage == null) { // Using the component stored in config if no package name. final boolean useSystemProvidedLauncher = mContext.getResources().getBoolean( com.android.internal.R.bool.config_useSystemProvidedLauncherForSecondary); if (preferredPackage == null || useSystemProvidedLauncher) { // Using the component stored in config if no package name or forced. final String secondaryHomeComponent = mContext.getResources().getString( com.android.internal.R.string.config_secondaryHomeComponent); intent.setComponent(ComponentName.unflattenFromString(secondaryHomeComponent)); Loading
services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +69 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.ActivityDisplay.POSITION_TOP; Loading @@ -54,6 +55,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.util.Pair; Loading Loading @@ -600,6 +602,73 @@ public class RootActivityContainerTests extends ActivityTestsBase { assertEquals(comp.getClassName(), resolvedInfo.first.name); } /** * Tests that the default secondary home activity is always picked when it is in forced by * config_useSystemProvidedLauncherForSecondary. */ @Test public void testResolveSecondaryHomeActivityForced() throws Exception { Resources resources = mContext.getResources(); spyOn(resources); try { // setUp: set secondary launcher and force it. final String defaultSecondaryHome = "com.android.test/com.android.test.TestDefaultSecondaryHome"; final ComponentName secondaryComp = ComponentName.unflattenFromString( defaultSecondaryHome); doReturn(defaultSecondaryHome).when(resources).getString( com.android.internal.R.string.config_secondaryHomeComponent); doReturn(true).when(resources).getBoolean( com.android.internal.R.bool.config_useSystemProvidedLauncherForSecondary); final Intent secondaryHomeIntent = mService.getSecondaryHomeIntent(null); assertEquals(secondaryComp, secondaryHomeIntent.getComponent()); final ActivityInfo aInfoSecondary = new ActivityInfo(); aInfoSecondary.name = secondaryComp.getClassName(); aInfoSecondary.applicationInfo = new ApplicationInfo(); aInfoSecondary.applicationInfo.packageName = secondaryComp.getPackageName(); doReturn(aInfoSecondary).when(mRootActivityContainer).resolveHomeActivity(anyInt(), refEq(secondaryHomeIntent)); final Intent homeIntent = mService.getHomeIntent(); final ActivityInfo aInfoDefault = new ActivityInfo(); aInfoDefault.name = "fakeHomeActivity"; aInfoDefault.applicationInfo = new ApplicationInfo(); aInfoDefault.applicationInfo.packageName = "fakeHomePackage"; doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(), refEq(homeIntent)); // Let resolveActivities call to validate both main launcher and second launcher so that // resolveActivities call does not work as enabler for secondary. final List<ResolveInfo> resolutions1 = new ArrayList<>(); final ResolveInfo resolveInfo1 = new ResolveInfo(); resolveInfo1.activityInfo = new ActivityInfo(); resolveInfo1.activityInfo.name = aInfoDefault.name; resolveInfo1.activityInfo.applicationInfo = aInfoDefault.applicationInfo; resolutions1.add(resolveInfo1); doReturn(resolutions1).when(mRootActivityContainer).resolveActivities(anyInt(), refEq(homeIntent)); final List<ResolveInfo> resolutions2 = new ArrayList<>(); final ResolveInfo resolveInfo2 = new ResolveInfo(); resolveInfo2.activityInfo = new ActivityInfo(); resolveInfo2.activityInfo.name = aInfoSecondary.name; resolveInfo2.activityInfo.applicationInfo = aInfoSecondary.applicationInfo; resolutions2.add(resolveInfo2); doReturn(resolutions2).when(mRootActivityContainer).resolveActivities(anyInt(), refEq(secondaryHomeIntent)); doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay( any(), anyInt(), anyBoolean()); // Run the test final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer .resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */); assertEquals(secondaryComp.getClassName(), resolvedInfo.first.name); assertEquals(secondaryComp.getPackageName(), resolvedInfo.first.applicationInfo.packageName); assertEquals(aInfoSecondary.name, resolvedInfo.first.name); } finally { // tearDown reset(resources); } } /** * Tests that secondary home should be selected if default home not support secondary displays * or there is no matched activity in the same package as selected default home. Loading