Replace PackageManagerInternal with PackageManager.

PackageManagerInternal in LocaleManagerService allowed any app to query
for another app's existence by looking at the exception message thrown
by the LocaleManager's get/set APIs. External PM, on the other hand,
does package visibility filtering which restricts regular apps from
querying information about other apps.

Bug: 225881167
Bug: 226900861

Test: atest CtsLocaleManagerTestCases
Test: atest CtsLocaleManagerHostTestCases
Test: atest CtsBackupTestCases:AppLocalesBackupTest
Test: atest LocaleManagerServiceTest
Test: atest LocaleManagerBackupRestoreTest
Test: atest SystemAppUpdateTrackerTest
Test: Manually tested by flashing and verifying that the test app
(PocProject) attached in the bug is not able to query app existence, and
also verifying that Settings and PlayStore are able to get/set any app's
locales. Also tested multi-user and work profiles.

Change-Id: If00016e7afd7f6552b6c66984cc0194d1bc449b1
This commit is contained in:
Nishant Kumar Singh
2022-04-01 12:21:19 +00:00
parent 39921c5b4a
commit ed7a616938
6 changed files with 62 additions and 71 deletions

View File

@@ -30,8 +30,6 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.HandlerThread;
import android.os.LocaleList;
import android.os.RemoteException;
@@ -78,7 +76,7 @@ class LocaleManagerBackupHelper {
private static final Duration STAGE_DATA_RETENTION_PERIOD = Duration.ofDays(3);
private final LocaleManagerService mLocaleManagerService;
private final PackageManagerInternal mPackageManagerInternal;
private final PackageManager mPackageManager;
private final Clock mClock;
private final Context mContext;
private final Object mStagedDataLock = new Object();
@@ -90,18 +88,18 @@ class LocaleManagerBackupHelper {
private final BroadcastReceiver mUserMonitor;
LocaleManagerBackupHelper(LocaleManagerService localeManagerService,
PackageManagerInternal pmInternal, HandlerThread broadcastHandlerThread) {
this(localeManagerService.mContext, localeManagerService, pmInternal, Clock.systemUTC(),
PackageManager packageManager, HandlerThread broadcastHandlerThread) {
this(localeManagerService.mContext, localeManagerService, packageManager, Clock.systemUTC(),
new SparseArray<>(), broadcastHandlerThread);
}
@VisibleForTesting LocaleManagerBackupHelper(Context context,
LocaleManagerService localeManagerService,
PackageManagerInternal pmInternal, Clock clock, SparseArray<StagedData> stagedData,
PackageManager packageManager, Clock clock, SparseArray<StagedData> stagedData,
HandlerThread broadcastHandlerThread) {
mContext = context;
mLocaleManagerService = localeManagerService;
mPackageManagerInternal = pmInternal;
mPackageManager = packageManager;
mClock = clock;
mStagedData = stagedData;
@@ -130,8 +128,8 @@ class LocaleManagerBackupHelper {
}
HashMap<String, String> pkgStates = new HashMap<>();
for (ApplicationInfo appInfo : mPackageManagerInternal.getInstalledApplications(/*flags*/0,
userId, Binder.getCallingUid())) {
for (ApplicationInfo appInfo : mPackageManager.getInstalledApplicationsAsUser(
PackageManager.ApplicationInfoFlags.of(0), userId)) {
try {
LocaleList appLocales = mLocaleManagerService.getApplicationLocales(
appInfo.packageName,

View File

@@ -28,7 +28,7 @@ import android.app.ILocaleManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManager.PackageInfoFlags;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.HandlerThread;
@@ -60,7 +60,7 @@ public class LocaleManagerService extends SystemService {
private final LocaleManagerService.LocaleManagerBinderService mBinderService;
private ActivityTaskManagerInternal mActivityTaskManagerInternal;
private ActivityManagerInternal mActivityManagerInternal;
private PackageManagerInternal mPackageManagerInternal;
private PackageManager mPackageManager;
private LocaleManagerBackupHelper mBackupHelper;
@@ -74,7 +74,7 @@ public class LocaleManagerService extends SystemService {
mBinderService = new LocaleManagerBinderService();
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mPackageManager = mContext.getPackageManager();
HandlerThread broadcastHandlerThread = new HandlerThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND);
@@ -90,7 +90,7 @@ public class LocaleManagerService extends SystemService {
});
mBackupHelper = new LocaleManagerBackupHelper(this,
mPackageManagerInternal, broadcastHandlerThread);
mPackageManager, broadcastHandlerThread);
mPackageMonitor = new LocaleManagerServicePackageMonitor(mBackupHelper,
systemAppUpdateTracker);
@@ -102,7 +102,7 @@ public class LocaleManagerService extends SystemService {
@VisibleForTesting
LocaleManagerService(Context context, ActivityTaskManagerInternal activityTaskManagerInternal,
ActivityManagerInternal activityManagerInternal,
PackageManagerInternal packageManagerInternal,
PackageManager packageManager,
LocaleManagerBackupHelper localeManagerBackupHelper,
PackageMonitor packageMonitor) {
super(context);
@@ -110,7 +110,7 @@ public class LocaleManagerService extends SystemService {
mBinderService = new LocaleManagerBinderService();
mActivityTaskManagerInternal = activityTaskManagerInternal;
mActivityManagerInternal = activityManagerInternal;
mPackageManagerInternal = packageManagerInternal;
mPackageManager = packageManager;
mBackupHelper = localeManagerBackupHelper;
mPackageMonitor = packageMonitor;
}
@@ -419,8 +419,12 @@ public class LocaleManagerService extends SystemService {
}
private int getPackageUid(String appPackageName, int userId) {
return mPackageManagerInternal
.getPackageUid(appPackageName, /* flags */ 0, userId);
try {
return mPackageManager
.getPackageUidAsUser(appPackageName, PackageInfoFlags.of(0), userId);
} catch (PackageManager.NameNotFoundException e) {
return Process.INVALID_UID;
}
}
@Nullable

View File

@@ -22,7 +22,6 @@ import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
@@ -39,7 +38,6 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.HandlerThread;
import android.os.LocaleList;
@@ -102,8 +100,6 @@ public class LocaleManagerBackupRestoreTest {
@Mock
private Context mMockContext;
@Mock
private PackageManagerInternal mMockPackageManagerInternal;
@Mock
private PackageManager mMockPackageManager;
@Mock
private LocaleManagerService mMockLocaleManagerService;
@@ -129,7 +125,6 @@ public class LocaleManagerBackupRestoreTest {
@Before
public void setUp() throws Exception {
mMockContext = mock(Context.class);
mMockPackageManagerInternal = mock(PackageManagerInternal.class);
mMockPackageManager = mock(PackageManager.class);
mMockLocaleManagerService = mock(LocaleManagerService.class);
SystemAppUpdateTracker systemAppUpdateTracker = mock(SystemAppUpdateTracker.class);
@@ -141,7 +136,7 @@ public class LocaleManagerBackupRestoreTest {
broadcastHandlerThread.start();
mBackupHelper = spy(new ShadowLocaleManagerBackupHelper(mMockContext,
mMockLocaleManagerService, mMockPackageManagerInternal, mClock, STAGE_DATA,
mMockLocaleManagerService, mMockPackageManager, mClock, STAGE_DATA,
broadcastHandlerThread));
doNothing().when(mBackupHelper).notifyBackupManager();
@@ -158,8 +153,8 @@ public class LocaleManagerBackupRestoreTest {
@Test
public void testBackupPayload_noAppsInstalled_returnsNull() throws Exception {
doReturn(List.of()).when(mMockPackageManagerInternal)
.getInstalledApplications(anyLong(), anyInt(), anyInt());
doReturn(List.of()).when(mMockPackageManager)
.getInstalledApplicationsAsUser(any(), anyInt());
assertNull(mBackupHelper.getBackupPayload(DEFAULT_USER_ID));
}
@@ -198,8 +193,8 @@ public class LocaleManagerBackupRestoreTest {
ApplicationInfo anotherAppInfo = new ApplicationInfo();
defaultAppInfo.packageName = DEFAULT_PACKAGE_NAME;
anotherAppInfo.packageName = "com.android.anotherapp";
doReturn(List.of(defaultAppInfo, anotherAppInfo)).when(mMockPackageManagerInternal)
.getInstalledApplications(anyLong(), anyInt(), anyInt());
doReturn(List.of(defaultAppInfo, anotherAppInfo)).when(mMockPackageManager)
.getInstalledApplicationsAsUser(any(), anyInt());
setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, DEFAULT_LOCALES);
// Exception when getting locales for anotherApp.
@@ -447,8 +442,8 @@ public class LocaleManagerBackupRestoreTest {
// Retention period has not elapsed.
setCurrentTimeMillis(
DEFAULT_CREATION_TIME_MILLIS + RETENTION_PERIOD.minusHours(1).toMillis());
doReturn(List.of()).when(mMockPackageManagerInternal)
.getInstalledApplications(anyLong(), anyInt(), anyInt());
doReturn(List.of()).when(mMockPackageManager)
.getInstalledApplicationsAsUser(any(), anyInt());
assertNull(mBackupHelper.getBackupPayload(DEFAULT_USER_ID));
checkStageDataExists(DEFAULT_USER_ID);
@@ -456,8 +451,8 @@ public class LocaleManagerBackupRestoreTest {
// Exactly RETENTION_PERIOD amount of time has passed so stage data should still not be
// removed.
setCurrentTimeMillis(DEFAULT_CREATION_TIME_MILLIS + RETENTION_PERIOD.toMillis());
doReturn(List.of()).when(mMockPackageManagerInternal)
.getInstalledApplications(anyLong(), anyInt(), anyInt());
doReturn(List.of()).when(mMockPackageManager)
.getInstalledApplicationsAsUser(any(), anyInt());
assertNull(mBackupHelper.getBackupPayload(DEFAULT_USER_ID));
checkStageDataExists(DEFAULT_USER_ID);
@@ -465,8 +460,8 @@ public class LocaleManagerBackupRestoreTest {
// Retention period has now expired, stage data should be deleted.
setCurrentTimeMillis(
DEFAULT_CREATION_TIME_MILLIS + RETENTION_PERIOD.plusSeconds(1).toMillis());
doReturn(List.of()).when(mMockPackageManagerInternal)
.getInstalledApplications(anyLong(), anyInt(), anyInt());
doReturn(List.of()).when(mMockPackageManager)
.getInstalledApplicationsAsUser(any(), anyInt());
assertNull(mBackupHelper.getBackupPayload(DEFAULT_USER_ID));
checkStageDataDoesNotExist(DEFAULT_USER_ID);
@@ -577,8 +572,8 @@ public class LocaleManagerBackupRestoreTest {
private void setUpDummyAppForPackageManager(String packageName) {
ApplicationInfo dummyApp = new ApplicationInfo();
dummyApp.packageName = packageName;
doReturn(List.of(dummyApp)).when(mMockPackageManagerInternal)
.getInstalledApplications(anyLong(), anyInt(), anyInt());
doReturn(List.of(dummyApp)).when(mMockPackageManager)
.getInstalledApplicationsAsUser(any(), anyInt());
}
/**

View File

@@ -23,7 +23,6 @@ import static junit.framework.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
@@ -40,7 +39,6 @@ import android.content.Context;
import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.LocaleList;
@@ -80,7 +78,7 @@ public class LocaleManagerServiceTest {
@Mock
private Context mMockContext;
@Mock
private PackageManagerInternal mMockPackageManagerInternal;
private PackageManager mMockPackageManager;
@Mock
private FakePackageConfigurationUpdater mFakePackageConfigurationUpdater;
@Mock
@@ -95,14 +93,13 @@ public class LocaleManagerServiceTest {
mMockContext = mock(Context.class);
mMockActivityTaskManager = mock(ActivityTaskManagerInternal.class);
mMockActivityManager = mock(ActivityManagerInternal.class);
mMockPackageManagerInternal = mock(PackageManagerInternal.class);
mMockPackageManager = mock(PackageManager.class);
mMockPackageMonitor = mock(PackageMonitor.class);
// For unit tests, set the default installer info
PackageManager mockPackageManager = mock(PackageManager.class);
doReturn(DEFAULT_INSTALL_SOURCE_INFO).when(mockPackageManager)
doReturn(DEFAULT_INSTALL_SOURCE_INFO).when(mMockPackageManager)
.getInstallSourceInfo(anyString());
doReturn(mockPackageManager).when(mMockContext).getPackageManager();
doReturn(mMockPackageManager).when(mMockContext).getPackageManager();
mFakePackageConfigurationUpdater = new FakePackageConfigurationUpdater();
doReturn(mFakePackageConfigurationUpdater)
@@ -117,14 +114,14 @@ public class LocaleManagerServiceTest {
mMockBackupHelper = mock(ShadowLocaleManagerBackupHelper.class);
mLocaleManagerService = new LocaleManagerService(mMockContext, mMockActivityTaskManager,
mMockActivityManager, mMockPackageManagerInternal,
mMockActivityManager, mMockPackageManager,
mMockBackupHelper, mMockPackageMonitor);
}
@Test(expected = SecurityException.class)
public void testSetApplicationLocales_arbitraryAppWithoutPermissions_fails() throws Exception {
doReturn(DEFAULT_UID)
.when(mMockPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt());
.when(mMockPackageManager).getPackageUidAsUser(anyString(), any(), anyInt());
setUpFailingPermissionCheckFor(Manifest.permission.CHANGE_CONFIGURATION);
try {
@@ -170,7 +167,7 @@ public class LocaleManagerServiceTest {
@Test
public void testSetApplicationLocales_arbitraryAppWithPermission_succeeds() throws Exception {
doReturn(DEFAULT_UID)
.when(mMockPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt());
.when(mMockPackageManager).getPackageUidAsUser(anyString(), any(), anyInt());
// if package is not owned by the caller, the calling app should have the following
// permission. We will mock this to succeed to imitate that.
setUpPassingPermissionCheckFor(Manifest.permission.CHANGE_CONFIGURATION);
@@ -186,7 +183,7 @@ public class LocaleManagerServiceTest {
@Test
public void testSetApplicationLocales_callerOwnsPackage_succeeds() throws Exception {
doReturn(Binder.getCallingUid())
.when(mMockPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt());
.when(mMockPackageManager).getPackageUidAsUser(anyString(), any(), anyInt());
mLocaleManagerService.setApplicationLocales(DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID,
DEFAULT_LOCALES);
@@ -197,8 +194,8 @@ public class LocaleManagerServiceTest {
@Test(expected = IllegalArgumentException.class)
public void testSetApplicationLocales_invalidPackageOrUserId_fails() throws Exception {
doReturn(INVALID_UID)
.when(mMockPackageManagerInternal).getPackageUid(anyString(), anyLong(), anyInt());
doThrow(new PackageManager.NameNotFoundException("Mock"))
.when(mMockPackageManager).getPackageUidAsUser(anyString(), any(), anyInt());
try {
mLocaleManagerService.setApplicationLocales(DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID,
LocaleList.getEmptyLocaleList());
@@ -211,8 +208,8 @@ public class LocaleManagerServiceTest {
@Test(expected = SecurityException.class)
public void testGetApplicationLocales_arbitraryAppWithoutPermission_fails() throws Exception {
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
.getPackageUid(anyString(), anyLong(), anyInt());
doReturn(DEFAULT_UID).when(mMockPackageManager)
.getPackageUidAsUser(anyString(), any(), anyInt());
setUpFailingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES);
try {
@@ -229,8 +226,8 @@ public class LocaleManagerServiceTest {
public void testGetApplicationLocales_appSpecificConfigAbsent_returnsEmptyList()
throws Exception {
// any valid app calling for its own package or having appropriate permission
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
.getPackageUid(anyString(), anyLong(), anyInt());
doReturn(DEFAULT_UID).when(mMockPackageManager)
.getPackageUidAsUser(anyString(), any(), anyInt());
setUpPassingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES);
doReturn(null)
.when(mMockActivityTaskManager).getApplicationConfig(anyString(), anyInt());
@@ -244,8 +241,8 @@ public class LocaleManagerServiceTest {
@Test
public void testGetApplicationLocales_appSpecificLocalesAbsent_returnsEmptyList()
throws Exception {
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
.getPackageUid(anyString(), anyLong(), anyInt());
doReturn(DEFAULT_UID).when(mMockPackageManager)
.getPackageUidAsUser(anyString(), any(), anyInt());
setUpPassingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES);
doReturn(new PackageConfig(/* nightMode = */ 0, /* locales = */ null))
.when(mMockActivityTaskManager).getApplicationConfig(any(), anyInt());
@@ -259,8 +256,8 @@ public class LocaleManagerServiceTest {
@Test
public void testGetApplicationLocales_callerOwnsAppAndConfigPresent_returnsLocales()
throws Exception {
doReturn(Binder.getCallingUid()).when(mMockPackageManagerInternal)
.getPackageUid(anyString(), anyLong(), anyInt());
doReturn(Binder.getCallingUid()).when(mMockPackageManager)
.getPackageUidAsUser(anyString(), any(), anyInt());
doReturn(new PackageConfig(/* nightMode = */ 0, DEFAULT_LOCALES))
.when(mMockActivityTaskManager).getApplicationConfig(anyString(), anyInt());
@@ -273,8 +270,8 @@ public class LocaleManagerServiceTest {
@Test
public void testGetApplicationLocales_arbitraryCallerWithPermissions_returnsLocales()
throws Exception {
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
.getPackageUid(anyString(), anyLong(), anyInt());
doReturn(DEFAULT_UID).when(mMockPackageManager)
.getPackageUidAsUser(anyString(), any(), anyInt());
setUpPassingPermissionCheckFor(Manifest.permission.READ_APP_SPECIFIC_LOCALES);
doReturn(new PackageConfig(/* nightMode = */ 0, DEFAULT_LOCALES))
.when(mMockActivityTaskManager).getApplicationConfig(anyString(), anyInt());
@@ -288,10 +285,10 @@ public class LocaleManagerServiceTest {
@Test
public void testGetApplicationLocales_callerIsInstaller_returnsLocales()
throws Exception {
doReturn(DEFAULT_UID).when(mMockPackageManagerInternal)
.getPackageUid(eq(DEFAULT_PACKAGE_NAME), anyLong(), anyInt());
doReturn(Binder.getCallingUid()).when(mMockPackageManagerInternal)
.getPackageUid(eq(DEFAULT_INSTALLER_PACKAGE_NAME), anyLong(), anyInt());
doReturn(DEFAULT_UID).when(mMockPackageManager)
.getPackageUidAsUser(eq(DEFAULT_PACKAGE_NAME), any(), anyInt());
doReturn(Binder.getCallingUid()).when(mMockPackageManager)
.getPackageUidAsUser(eq(DEFAULT_INSTALLER_PACKAGE_NAME), any(), anyInt());
doReturn(new PackageConfig(/* nightMode = */ 0, DEFAULT_LOCALES))
.when(mMockActivityTaskManager).getApplicationConfig(anyString(), anyInt());

View File

@@ -17,7 +17,7 @@
package com.android.server.locales;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManager;
import android.os.HandlerThread;
import android.util.SparseArray;
@@ -31,9 +31,10 @@ import java.time.Clock;
public class ShadowLocaleManagerBackupHelper extends LocaleManagerBackupHelper {
ShadowLocaleManagerBackupHelper(Context context,
LocaleManagerService localeManagerService,
PackageManagerInternal pmInternal, Clock clock,
PackageManager packageManager, Clock clock,
SparseArray<LocaleManagerBackupHelper.StagedData> stagedData,
HandlerThread broadcastHandlerThread) {
super(context, localeManagerService, pmInternal, clock, stagedData, broadcastHandlerThread);
super(context, localeManagerService, packageManager, clock, stagedData,
broadcastHandlerThread);
}
}

View File

@@ -38,7 +38,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.Environment;
import android.os.LocaleList;
@@ -93,8 +92,6 @@ public class SystemAppUpdateTrackerTest {
@Mock
PackageManager mMockPackageManager;
@Mock
private PackageManagerInternal mMockPackageManagerInternal;
@Mock
private ActivityTaskManagerInternal mMockActivityTaskManager;
@Mock
private ActivityManagerInternal mMockActivityManager;
@@ -110,21 +107,20 @@ public class SystemAppUpdateTrackerTest {
mMockContext = mock(Context.class);
mMockActivityTaskManager = mock(ActivityTaskManagerInternal.class);
mMockActivityManager = mock(ActivityManagerInternal.class);
mMockPackageManagerInternal = mock(PackageManagerInternal.class);
mMockPackageManager = mock(PackageManager.class);
LocaleManagerBackupHelper mockLocaleManagerBackupHelper =
mock(ShadowLocaleManagerBackupHelper.class);
// PackageMonitor is not needed in LocaleManagerService for these tests hence it is
// passed as null.
mLocaleManagerService = new LocaleManagerService(mMockContext,
mMockActivityTaskManager, mMockActivityManager,
mMockPackageManagerInternal, mockLocaleManagerBackupHelper,
mMockPackageManager, mockLocaleManagerBackupHelper,
/* mPackageMonitor= */ null);
doReturn(DEFAULT_USER_ID).when(mMockActivityManager)
.handleIncomingUser(anyInt(), anyInt(), eq(DEFAULT_USER_ID), anyBoolean(), anyInt(),
anyString(), anyString());
mMockPackageManager = mock(PackageManager.class);
doReturn(DEFAULT_INSTALL_SOURCE_INFO).when(mMockPackageManager)
.getInstallSourceInfo(anyString());
doReturn(mMockPackageManager).when(mMockContext).getPackageManager();