diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java index 364f6db28f03a..4ce03205fc1c9 100644 --- a/services/core/java/com/android/server/locales/LocaleManagerService.java +++ b/services/core/java/com/android/server/locales/LocaleManagerService.java @@ -364,16 +364,19 @@ public class LocaleManagerService extends SystemService { // 1.) A normal, non-privileged app querying its own locale. // 2.) The installer of the given app querying locales of a package installed by said // installer. - // 3.) The current input method querying locales of another package. + // 3.) The current input method querying locales of the current foreground app. // 4.) A privileged system service querying locales of another package. // The least privileged case is a normal app performing a query, so check that first and get // locales if the package name is owned by the app. Next check if the calling app is the // installer of the given app and get locales. Finally check if the calling app is the - // current input method. If neither conditions matched, check if the caller has the - // necessary permission and fetch locales. + // current input method, and that app is querying locales of the current foreground app. If + // neither conditions matched, check if the caller has the necessary permission and fetch + // locales. if (!isPackageOwnedByCaller(appPackageName, userId) && !isCallerInstaller(appPackageName, userId) - && !isCallerFromCurrentInputMethod(userId)) { + && !(isCallerFromCurrentInputMethod(userId) + && mActivityManagerInternal.isAppForeground( + getPackageUid(appPackageName, userId)))) { enforceReadAppSpecificLocalesPermission(); } final long token = Binder.clearCallingIdentity(); diff --git a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java index dbcd38c35958d..dc9f907377138 100644 --- a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java @@ -229,6 +229,29 @@ public class LocaleManagerServiceTest { } } + @Test(expected = SecurityException.class) + public void testGetApplicationLocales_currentImeQueryNonForegroundAppLocales_fails() + throws Exception { + doReturn(DEFAULT_UID).when(mMockPackageManager) + .getPackageUidAsUser(anyString(), any(), anyInt()); + doReturn(new PackageConfig(/* nightMode = */ 0, DEFAULT_LOCALES)) + .when(mMockActivityTaskManager).getApplicationConfig(anyString(), anyInt()); + String imPkgName = getCurrentInputMethodPackageName(); + doReturn(Binder.getCallingUid()).when(mMockPackageManager) + .getPackageUidAsUser(eq(imPkgName), any(), anyInt()); + doReturn(false).when(mMockActivityManager).isAppForeground(anyInt()); + setUpFailingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES); + + try { + mLocaleManagerService.getApplicationLocales(DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID); + fail("Expected SecurityException"); + } finally { + verify(mMockContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.READ_APP_SPECIFIC_LOCALES), + anyString()); + } + } + @Test public void testGetApplicationLocales_appSpecificConfigAbsent_returnsEmptyList() throws Exception { @@ -307,7 +330,7 @@ public class LocaleManagerServiceTest { } @Test - public void testGetApplicationLocales_callerIsCurrentInputMethod_returnsLocales() + public void testGetApplicationLocales_currentImeQueryForegroundAppLocales_returnsLocales() throws Exception { doReturn(DEFAULT_UID).when(mMockPackageManager) .getPackageUidAsUser(anyString(), any(), anyInt()); @@ -316,6 +339,7 @@ public class LocaleManagerServiceTest { String imPkgName = getCurrentInputMethodPackageName(); doReturn(Binder.getCallingUid()).when(mMockPackageManager) .getPackageUidAsUser(eq(imPkgName), any(), anyInt()); + doReturn(true).when(mMockActivityManager).isAppForeground(anyInt()); LocaleList locales = mLocaleManagerService.getApplicationLocales(