Loading src/com/android/settings/localepicker/AppLocalePickerActivity.java +16 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.settings.localepicker; import android.app.FragmentTransaction; import android.app.LocaleManager; import android.content.Context; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.os.LocaleList; Loading @@ -34,6 +35,7 @@ import com.android.internal.app.LocalePickerWithRegion; import com.android.internal.app.LocaleStore; import com.android.settings.R; import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppLocaleUtil; import com.android.settings.applications.appinfo.AppLocaleDetails; import com.android.settings.core.SettingsBaseActivity; Loading Loading @@ -64,12 +66,17 @@ public class AppLocalePickerActivity extends SettingsBaseActivity } mContextAsUser = this; if (getIntent().hasExtra(AppInfoBase.ARG_PACKAGE_UID)) { int userId = getIntent().getIntExtra(AppInfoBase.ARG_PACKAGE_UID, -1); if (userId != -1) { UserHandle userHandle = UserHandle.getUserHandleForUid(userId); int uid = getIntent().getIntExtra(AppInfoBase.ARG_PACKAGE_UID, -1); if (uid != -1) { UserHandle userHandle = UserHandle.getUserHandleForUid(uid); mContextAsUser = createContextAsUser(userHandle, 0); } } if (!canDisplayLocaleUi() || mContextAsUser.getUserId() != UserHandle.myUserId()) { Log.w(TAG, "Not allow to display Locale Settings UI."); finish(); return; } setTitle(R.string.app_locale_picker_title); getActionBar().setDisplayHomeAsUpEnabled(true); Loading Loading @@ -160,4 +167,10 @@ public class AppLocalePickerActivity extends SettingsBaseActivity .replace(R.id.content_frame, mLocalePickerWithRegion) .commit(); } private boolean canDisplayLocaleUi() { return AppLocaleUtil.canDisplayLocaleUi(mContextAsUser, mPackageName, mContextAsUser.getPackageManager().queryIntentActivities( AppLocaleUtil.LAUNCHER_ENTRY_INTENT, PackageManager.GET_META_DATA)); } } tests/robotests/src/com/android/settings/localepicker/AppLocalePickerActivityTest.java +167 −5 Original line number Diff line number Diff line Loading @@ -18,25 +18,35 @@ package com.android.settings.localepicker; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.app.Activity; import android.app.ApplicationPackageManager; import android.app.LocaleConfig; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.InstallSourceInfo; import android.content.pm.PackageInfo; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.net.Uri; import android.os.LocaleList; import android.os.Process; import android.os.UserHandle; import android.telephony.TelephonyManager; import androidx.annotation.ArrayRes; import com.android.internal.app.LocaleStore; import com.android.settings.applications.AppInfoBase; import java.util.Locale; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -45,17 +55,26 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.Shadows; import org.robolectric.android.controller.ActivityController; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.shadows.ShadowPackageManager; import org.robolectric.shadows.ShadowTelephonyManager; import java.util.ArrayList; import java.util.List; import java.util.Locale; @RunWith(RobolectricTestRunner.class) @Config( shadows = { AppLocalePickerActivityTest.ShadowApplicationPackageManager.class, AppLocalePickerActivityTest.ShadowResources.class, AppLocalePickerActivityTest.ShadowUserHandle.class, AppLocalePickerActivityTest.ShadowLocaleConfig.class, }) public class AppLocalePickerActivityTest { private static final String TEST_PACKAGE_NAME = "com.android.settings"; Loading @@ -67,21 +86,99 @@ public class AppLocalePickerActivityTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); private Context mContext; private ShadowPackageManager mPackageManager; @Before public void setUp() { mContext = spy(RuntimeEnvironment.application); mPackageManager = Shadows.shadowOf(mContext.getPackageManager()); } @After public void tearDown() { mPackageManager.removePackage(TEST_PACKAGE_NAME); ShadowResources.setDisAllowPackage(false); ShadowApplicationPackageManager.setNoLaunchEntry(false); ShadowUserHandle.setUserId(0); ShadowLocaleConfig.setStatus(LocaleConfig.STATUS_SUCCESS); } @Test public void launchAppLocalePickerActivity_hasPackageName_success() { ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isFalse(); } @Test public void launchAppLocalePickerActivity_appNoLocaleConfig_failed() { ShadowLocaleConfig.setStatus(LocaleConfig.STATUS_NOT_SPECIFIED); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_appSignPlatformKey_failed() { final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY; applicationInfo.packageName = TEST_PACKAGE_NAME; final PackageInfo packageInfo = new PackageInfo(); packageInfo.packageName = TEST_PACKAGE_NAME; packageInfo.applicationInfo = applicationInfo; mPackageManager.installPackage(packageInfo); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_appMatchDisallowedPackage_failed() { ShadowResources.setDisAllowPackage(true); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_appNoLaunchEntry_failed() { ShadowApplicationPackageManager.setNoLaunchEntry(true); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_modifyAppLocalesOfAnotherUser_failed() { ShadowUserHandle.setUserId(10); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_intentWithoutPackageName_failed() { ActivityController<TestAppLocalePickerActivity> controller = initActivityController(false); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); Loading Loading @@ -125,7 +222,7 @@ public class AppLocalePickerActivityTest { if (hasPackageName) { data.setData(TEST_PACKAGE_URI); } data.putExtra(AppInfoBase.ARG_PACKAGE_UID, UserHandle.getUserId(Process.myUid())); data.putExtra(AppInfoBase.ARG_PACKAGE_UID, Process.myUid()); ActivityController<TestAppLocalePickerActivity> activityController = Robolectric.buildActivity(TestAppLocalePickerActivity.class, data); Activity activity = activityController.get(); Loading @@ -149,10 +246,75 @@ public class AppLocalePickerActivityTest { @Implements(ApplicationPackageManager.class) public static class ShadowApplicationPackageManager extends org.robolectric.shadows.ShadowApplicationPackageManager { private static boolean sNoLaunchEntry = false; @Implementation protected Object getInstallSourceInfo(String packageName) { return new InstallSourceInfo("", null, null, ""); } @Implementation protected List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { if (sNoLaunchEntry) { return new ArrayList(); } else { return super.queryIntentActivities(intent, flags); } } private static void setNoLaunchEntry(boolean noLaunchEntry) { sNoLaunchEntry = noLaunchEntry; } } @Implements(Resources.class) public static class ShadowResources extends org.robolectric.shadows.ShadowResources { private static boolean sDisAllowPackage = false; @Implementation public String[] getStringArray(@ArrayRes int id) { if (sDisAllowPackage) { return new String[]{TEST_PACKAGE_NAME}; } else { return new String[0]; } } private static void setDisAllowPackage(boolean disAllowPackage) { sDisAllowPackage = disAllowPackage; } } @Implements(UserHandle.class) public static class ShadowUserHandle { private static int sUserId = 0; private static void setUserId(int userId) { sUserId = userId; } @Implementation public static int getUserId(int userId) { return sUserId; } } @Implements(LocaleConfig.class) public static class ShadowLocaleConfig { private static int sStatus = 0; @Implementation public @Nullable LocaleList getSupportedLocales() { return LocaleList.forLanguageTags("en-US"); } private static void setStatus(@LocaleConfig.Status int status) { sStatus = status; } @Implementation public @LocaleConfig.Status int getStatus() { return sStatus; } } } Loading
src/com/android/settings/localepicker/AppLocalePickerActivity.java +16 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.settings.localepicker; import android.app.FragmentTransaction; import android.app.LocaleManager; import android.content.Context; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.os.LocaleList; Loading @@ -34,6 +35,7 @@ import com.android.internal.app.LocalePickerWithRegion; import com.android.internal.app.LocaleStore; import com.android.settings.R; import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppLocaleUtil; import com.android.settings.applications.appinfo.AppLocaleDetails; import com.android.settings.core.SettingsBaseActivity; Loading Loading @@ -64,12 +66,17 @@ public class AppLocalePickerActivity extends SettingsBaseActivity } mContextAsUser = this; if (getIntent().hasExtra(AppInfoBase.ARG_PACKAGE_UID)) { int userId = getIntent().getIntExtra(AppInfoBase.ARG_PACKAGE_UID, -1); if (userId != -1) { UserHandle userHandle = UserHandle.getUserHandleForUid(userId); int uid = getIntent().getIntExtra(AppInfoBase.ARG_PACKAGE_UID, -1); if (uid != -1) { UserHandle userHandle = UserHandle.getUserHandleForUid(uid); mContextAsUser = createContextAsUser(userHandle, 0); } } if (!canDisplayLocaleUi() || mContextAsUser.getUserId() != UserHandle.myUserId()) { Log.w(TAG, "Not allow to display Locale Settings UI."); finish(); return; } setTitle(R.string.app_locale_picker_title); getActionBar().setDisplayHomeAsUpEnabled(true); Loading Loading @@ -160,4 +167,10 @@ public class AppLocalePickerActivity extends SettingsBaseActivity .replace(R.id.content_frame, mLocalePickerWithRegion) .commit(); } private boolean canDisplayLocaleUi() { return AppLocaleUtil.canDisplayLocaleUi(mContextAsUser, mPackageName, mContextAsUser.getPackageManager().queryIntentActivities( AppLocaleUtil.LAUNCHER_ENTRY_INTENT, PackageManager.GET_META_DATA)); } }
tests/robotests/src/com/android/settings/localepicker/AppLocalePickerActivityTest.java +167 −5 Original line number Diff line number Diff line Loading @@ -18,25 +18,35 @@ package com.android.settings.localepicker; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.app.Activity; import android.app.ApplicationPackageManager; import android.app.LocaleConfig; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.InstallSourceInfo; import android.content.pm.PackageInfo; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.net.Uri; import android.os.LocaleList; import android.os.Process; import android.os.UserHandle; import android.telephony.TelephonyManager; import androidx.annotation.ArrayRes; import com.android.internal.app.LocaleStore; import com.android.settings.applications.AppInfoBase; import java.util.Locale; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -45,17 +55,26 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.Shadows; import org.robolectric.android.controller.ActivityController; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.shadows.ShadowPackageManager; import org.robolectric.shadows.ShadowTelephonyManager; import java.util.ArrayList; import java.util.List; import java.util.Locale; @RunWith(RobolectricTestRunner.class) @Config( shadows = { AppLocalePickerActivityTest.ShadowApplicationPackageManager.class, AppLocalePickerActivityTest.ShadowResources.class, AppLocalePickerActivityTest.ShadowUserHandle.class, AppLocalePickerActivityTest.ShadowLocaleConfig.class, }) public class AppLocalePickerActivityTest { private static final String TEST_PACKAGE_NAME = "com.android.settings"; Loading @@ -67,21 +86,99 @@ public class AppLocalePickerActivityTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); private Context mContext; private ShadowPackageManager mPackageManager; @Before public void setUp() { mContext = spy(RuntimeEnvironment.application); mPackageManager = Shadows.shadowOf(mContext.getPackageManager()); } @After public void tearDown() { mPackageManager.removePackage(TEST_PACKAGE_NAME); ShadowResources.setDisAllowPackage(false); ShadowApplicationPackageManager.setNoLaunchEntry(false); ShadowUserHandle.setUserId(0); ShadowLocaleConfig.setStatus(LocaleConfig.STATUS_SUCCESS); } @Test public void launchAppLocalePickerActivity_hasPackageName_success() { ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isFalse(); } @Test public void launchAppLocalePickerActivity_appNoLocaleConfig_failed() { ShadowLocaleConfig.setStatus(LocaleConfig.STATUS_NOT_SPECIFIED); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_appSignPlatformKey_failed() { final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY; applicationInfo.packageName = TEST_PACKAGE_NAME; final PackageInfo packageInfo = new PackageInfo(); packageInfo.packageName = TEST_PACKAGE_NAME; packageInfo.applicationInfo = applicationInfo; mPackageManager.installPackage(packageInfo); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_appMatchDisallowedPackage_failed() { ShadowResources.setDisAllowPackage(true); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_appNoLaunchEntry_failed() { ShadowApplicationPackageManager.setNoLaunchEntry(true); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_modifyAppLocalesOfAnotherUser_failed() { ShadowUserHandle.setUserId(10); ActivityController<TestAppLocalePickerActivity> controller = initActivityController(true); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); } @Test public void launchAppLocalePickerActivity_intentWithoutPackageName_failed() { ActivityController<TestAppLocalePickerActivity> controller = initActivityController(false); controller.create(); assertThat(controller.get().isFinishing()).isTrue(); Loading Loading @@ -125,7 +222,7 @@ public class AppLocalePickerActivityTest { if (hasPackageName) { data.setData(TEST_PACKAGE_URI); } data.putExtra(AppInfoBase.ARG_PACKAGE_UID, UserHandle.getUserId(Process.myUid())); data.putExtra(AppInfoBase.ARG_PACKAGE_UID, Process.myUid()); ActivityController<TestAppLocalePickerActivity> activityController = Robolectric.buildActivity(TestAppLocalePickerActivity.class, data); Activity activity = activityController.get(); Loading @@ -149,10 +246,75 @@ public class AppLocalePickerActivityTest { @Implements(ApplicationPackageManager.class) public static class ShadowApplicationPackageManager extends org.robolectric.shadows.ShadowApplicationPackageManager { private static boolean sNoLaunchEntry = false; @Implementation protected Object getInstallSourceInfo(String packageName) { return new InstallSourceInfo("", null, null, ""); } @Implementation protected List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { if (sNoLaunchEntry) { return new ArrayList(); } else { return super.queryIntentActivities(intent, flags); } } private static void setNoLaunchEntry(boolean noLaunchEntry) { sNoLaunchEntry = noLaunchEntry; } } @Implements(Resources.class) public static class ShadowResources extends org.robolectric.shadows.ShadowResources { private static boolean sDisAllowPackage = false; @Implementation public String[] getStringArray(@ArrayRes int id) { if (sDisAllowPackage) { return new String[]{TEST_PACKAGE_NAME}; } else { return new String[0]; } } private static void setDisAllowPackage(boolean disAllowPackage) { sDisAllowPackage = disAllowPackage; } } @Implements(UserHandle.class) public static class ShadowUserHandle { private static int sUserId = 0; private static void setUserId(int userId) { sUserId = userId; } @Implementation public static int getUserId(int userId) { return sUserId; } } @Implements(LocaleConfig.class) public static class ShadowLocaleConfig { private static int sStatus = 0; @Implementation public @Nullable LocaleList getSupportedLocales() { return LocaleList.forLanguageTags("en-US"); } private static void setStatus(@LocaleConfig.Status int status) { sStatus = status; } @Implementation public @LocaleConfig.Status int getStatus() { return sStatus; } } }