Loading services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java +41 −13 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Environment; import android.os.HandlerThread; import android.os.LocaleList; Loading Loading @@ -101,6 +102,11 @@ class LocaleManagerBackupHelper { // the application setting the app-locale itself. private final SharedPreferences mDelegateAppLocalePackages; private final BroadcastReceiver mUserMonitor; // To determine whether an app is pre-archived, check for Intent.EXTRA_ARCHIVAL upon receiving // the initial PACKAGE_ADDED broadcast. If it is indeed pre-archived, perform the data // restoration during the second PACKAGE_ADDED broadcast, which is sent subsequently when the // app is installed. private final Set<String> mPkgsToRestore; LocaleManagerBackupHelper(LocaleManagerService localeManagerService, PackageManager packageManager, HandlerThread broadcastHandlerThread) { Loading @@ -119,6 +125,7 @@ class LocaleManagerBackupHelper { mStagedData = stagedData; mDelegateAppLocalePackages = delegateAppLocalePackages != null ? delegateAppLocalePackages : createPersistedInfo(); mPkgsToRestore = new ArraySet<>(); mUserMonitor = new UserMonitor(); IntentFilter filter = new IntentFilter(); Loading Loading @@ -251,6 +258,9 @@ class LocaleManagerBackupHelper { LocalesInfo localesInfo = pkgStates.get(pkgName); // Check if the application is already installed for the concerned user. if (isPackageInstalledForUser(pkgName, userId)) { if (mPkgsToRestore != null) { mPkgsToRestore.remove(pkgName); } // Don't apply the restore if the locales have already been set for the app. checkExistingLocalesAndApplyRestore(pkgName, localesInfo, userId); } else { Loading Loading @@ -279,23 +289,18 @@ class LocaleManagerBackupHelper { /** * <p><b>Note:</b> This is invoked by service's common monitor * {@link LocaleManagerServicePackageMonitor#onPackageAdded} when a new package is * {@link LocaleManagerServicePackageMonitor#onPackageAddedWithExtras} when a new package is * added on device. */ void onPackageAdded(String packageName, int uid) { try { synchronized (mStagedDataLock) { cleanStagedDataForOldEntriesLocked(); int userId = UserHandle.getUserId(uid); if (mStagedData.contains(userId)) { // Perform lazy restore only if the staged data exists. doLazyRestoreLocked(packageName, userId); } void onPackageAddedWithExtras(String packageName, int uid, Bundle extras) { boolean archived = false; if (extras != null) { archived = extras.getBoolean(Intent.EXTRA_ARCHIVAL, false); if (archived && mPkgsToRestore != null) { mPkgsToRestore.add(packageName); } } catch (Exception e) { Slog.e(TAG, "Exception in onPackageAdded.", e); } checkStageDataAndApplyRestore(packageName, uid); } /** Loading @@ -305,6 +310,10 @@ class LocaleManagerBackupHelper { */ void onPackageUpdateFinished(String packageName, int uid) { int userId = UserHandle.getUserId(uid); if (mPkgsToRestore != null && mPkgsToRestore.contains(packageName)) { mPkgsToRestore.remove(packageName); checkStageDataAndApplyRestore(packageName, uid); } cleanApplicationLocalesIfNeeded(packageName, userId); } Loading Loading @@ -338,6 +347,25 @@ class LocaleManagerBackupHelper { } } private void checkStageDataAndApplyRestore(String packageName, int uid) { try { synchronized (mStagedDataLock) { cleanStagedDataForOldEntriesLocked(); int userId = UserHandle.getUserId(uid); if (mStagedData.contains(userId)) { if (mPkgsToRestore != null) { mPkgsToRestore.remove(packageName); } // Perform lazy restore only if the staged data exists. doLazyRestoreLocked(packageName, userId); } } } catch (Exception e) { Slog.e(TAG, "Exception in onPackageAdded.", e); } } private boolean isPackageInstalledForUser(String packageName, int userId) { PackageInfo pkgInfo = null; try { Loading services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java +3 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.locales; import android.annotation.NonNull; import android.os.Bundle; import android.os.UserHandle; import com.android.internal.content.PackageMonitor; Loading Loading @@ -48,8 +49,8 @@ final class LocaleManagerServicePackageMonitor extends PackageMonitor { } @Override public void onPackageAdded(String packageName, int uid) { mBackupHelper.onPackageAdded(packageName, uid); public void onPackageAddedWithExtras(String packageName, int uid, Bundle extras) { mBackupHelper.onPackageAddedWithExtras(packageName, uid, extras); } @Override Loading services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java +66 −5 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; import android.os.HandlerThread; import android.os.LocaleList; import android.os.Process; Loading Loading @@ -488,7 +489,7 @@ public class LocaleManagerBackupRestoreTest { setUpPackageInstalled(pkgNameA); mPackageMonitor.onPackageAdded(pkgNameA, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(pkgNameA, DEFAULT_UID, new Bundle()); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameA, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsA), false, FrameworkStatsLog Loading @@ -504,7 +505,67 @@ public class LocaleManagerBackupRestoreTest { setUpPackageInstalled(pkgNameB); mPackageMonitor.onPackageAdded(pkgNameB, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(pkgNameB, DEFAULT_UID, new Bundle()); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameB, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsB), true, FrameworkStatsLog .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_BACKUP_RESTORE); mBackupHelper.persistLocalesModificationInfo(DEFAULT_USER_ID, pkgNameB, true, false); verify(mMockSpEditor, times(1)).putStringSet(Integer.toString(DEFAULT_USER_ID), new ArraySet<>(Arrays.asList(pkgNameB))); checkStageDataDoesNotExist(DEFAULT_USER_ID); } @Test public void testRestore_appInstalledAfterSUW_restoresFromStage_ArchiveEnabled() throws Exception { final ByteArrayOutputStream out = new ByteArrayOutputStream(); HashMap<String, LocalesInfo> pkgLocalesMap = new HashMap<>(); String pkgNameA = "com.android.myAppA"; String pkgNameB = "com.android.myAppB"; String langTagsA = "ru"; String langTagsB = "hi,fr"; LocalesInfo localesInfoA = new LocalesInfo(langTagsA, false); LocalesInfo localesInfoB = new LocalesInfo(langTagsB, true); pkgLocalesMap.put(pkgNameA, localesInfoA); pkgLocalesMap.put(pkgNameB, localesInfoB); writeTestPayload(out, pkgLocalesMap); setUpPackageNotInstalled(pkgNameA); setUpPackageNotInstalled(pkgNameB); setUpLocalesForPackage(pkgNameA, LocaleList.getEmptyLocaleList()); setUpLocalesForPackage(pkgNameB, LocaleList.getEmptyLocaleList()); setUpPackageNamesForSp(new ArraySet<>()); Bundle bundle = new Bundle(); bundle.putBoolean(Intent.EXTRA_ARCHIVAL, true); mPackageMonitor.onPackageAddedWithExtras(pkgNameA, DEFAULT_UID, bundle); mPackageMonitor.onPackageAddedWithExtras(pkgNameB, DEFAULT_UID, bundle); mBackupHelper.stageAndApplyRestoredPayload(out.toByteArray(), DEFAULT_USER_ID); verifyNothingRestored(); setUpPackageInstalled(pkgNameA); mPackageMonitor.onPackageUpdateFinished(pkgNameA, DEFAULT_UID); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameA, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsA), false, FrameworkStatsLog .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_BACKUP_RESTORE); mBackupHelper.persistLocalesModificationInfo(DEFAULT_USER_ID, pkgNameA, false, false); verify(mMockSpEditor, times(0)).putStringSet(anyString(), any()); pkgLocalesMap.remove(pkgNameA); verifyStageDataForUser(pkgLocalesMap, DEFAULT_CREATION_TIME_MILLIS, DEFAULT_USER_ID); setUpPackageInstalled(pkgNameB); mPackageMonitor.onPackageUpdateFinished(pkgNameB, DEFAULT_UID); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameB, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsB), true, FrameworkStatsLog Loading Loading @@ -535,7 +596,7 @@ public class LocaleManagerBackupRestoreTest { setUpPackageInstalled(DEFAULT_PACKAGE_NAME); setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, LocaleList.forLanguageTags("hi,mr")); mPackageMonitor.onPackageAdded(DEFAULT_PACKAGE_NAME, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(DEFAULT_PACKAGE_NAME, DEFAULT_UID, new Bundle()); // Since locales are already set, we should not restore anything for it. verifyNothingRestored(); Loading Loading @@ -612,7 +673,7 @@ public class LocaleManagerBackupRestoreTest { DEFAULT_CREATION_TIME_MILLIS + RETENTION_PERIOD.minusHours(1).toMillis()); setUpPackageInstalled(pkgNameA); mPackageMonitor.onPackageAdded(pkgNameA, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(pkgNameA, DEFAULT_UID, new Bundle()); verify(mMockLocaleManagerService, times(1)).setApplicationLocales( pkgNameA, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsA), false, Loading @@ -627,7 +688,7 @@ public class LocaleManagerBackupRestoreTest { DEFAULT_CREATION_TIME_MILLIS + RETENTION_PERIOD.plusSeconds(1).toMillis()); setUpPackageInstalled(pkgNameB); mPackageMonitor.onPackageAdded(pkgNameB, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(pkgNameB, DEFAULT_UID, new Bundle()); verify(mMockLocaleManagerService, times(0)).setApplicationLocales(eq(pkgNameB), anyInt(), any(), anyBoolean(), anyInt()); Loading Loading
services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java +41 −13 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Environment; import android.os.HandlerThread; import android.os.LocaleList; Loading Loading @@ -101,6 +102,11 @@ class LocaleManagerBackupHelper { // the application setting the app-locale itself. private final SharedPreferences mDelegateAppLocalePackages; private final BroadcastReceiver mUserMonitor; // To determine whether an app is pre-archived, check for Intent.EXTRA_ARCHIVAL upon receiving // the initial PACKAGE_ADDED broadcast. If it is indeed pre-archived, perform the data // restoration during the second PACKAGE_ADDED broadcast, which is sent subsequently when the // app is installed. private final Set<String> mPkgsToRestore; LocaleManagerBackupHelper(LocaleManagerService localeManagerService, PackageManager packageManager, HandlerThread broadcastHandlerThread) { Loading @@ -119,6 +125,7 @@ class LocaleManagerBackupHelper { mStagedData = stagedData; mDelegateAppLocalePackages = delegateAppLocalePackages != null ? delegateAppLocalePackages : createPersistedInfo(); mPkgsToRestore = new ArraySet<>(); mUserMonitor = new UserMonitor(); IntentFilter filter = new IntentFilter(); Loading Loading @@ -251,6 +258,9 @@ class LocaleManagerBackupHelper { LocalesInfo localesInfo = pkgStates.get(pkgName); // Check if the application is already installed for the concerned user. if (isPackageInstalledForUser(pkgName, userId)) { if (mPkgsToRestore != null) { mPkgsToRestore.remove(pkgName); } // Don't apply the restore if the locales have already been set for the app. checkExistingLocalesAndApplyRestore(pkgName, localesInfo, userId); } else { Loading Loading @@ -279,23 +289,18 @@ class LocaleManagerBackupHelper { /** * <p><b>Note:</b> This is invoked by service's common monitor * {@link LocaleManagerServicePackageMonitor#onPackageAdded} when a new package is * {@link LocaleManagerServicePackageMonitor#onPackageAddedWithExtras} when a new package is * added on device. */ void onPackageAdded(String packageName, int uid) { try { synchronized (mStagedDataLock) { cleanStagedDataForOldEntriesLocked(); int userId = UserHandle.getUserId(uid); if (mStagedData.contains(userId)) { // Perform lazy restore only if the staged data exists. doLazyRestoreLocked(packageName, userId); } void onPackageAddedWithExtras(String packageName, int uid, Bundle extras) { boolean archived = false; if (extras != null) { archived = extras.getBoolean(Intent.EXTRA_ARCHIVAL, false); if (archived && mPkgsToRestore != null) { mPkgsToRestore.add(packageName); } } catch (Exception e) { Slog.e(TAG, "Exception in onPackageAdded.", e); } checkStageDataAndApplyRestore(packageName, uid); } /** Loading @@ -305,6 +310,10 @@ class LocaleManagerBackupHelper { */ void onPackageUpdateFinished(String packageName, int uid) { int userId = UserHandle.getUserId(uid); if (mPkgsToRestore != null && mPkgsToRestore.contains(packageName)) { mPkgsToRestore.remove(packageName); checkStageDataAndApplyRestore(packageName, uid); } cleanApplicationLocalesIfNeeded(packageName, userId); } Loading Loading @@ -338,6 +347,25 @@ class LocaleManagerBackupHelper { } } private void checkStageDataAndApplyRestore(String packageName, int uid) { try { synchronized (mStagedDataLock) { cleanStagedDataForOldEntriesLocked(); int userId = UserHandle.getUserId(uid); if (mStagedData.contains(userId)) { if (mPkgsToRestore != null) { mPkgsToRestore.remove(packageName); } // Perform lazy restore only if the staged data exists. doLazyRestoreLocked(packageName, userId); } } } catch (Exception e) { Slog.e(TAG, "Exception in onPackageAdded.", e); } } private boolean isPackageInstalledForUser(String packageName, int userId) { PackageInfo pkgInfo = null; try { Loading
services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java +3 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.locales; import android.annotation.NonNull; import android.os.Bundle; import android.os.UserHandle; import com.android.internal.content.PackageMonitor; Loading Loading @@ -48,8 +49,8 @@ final class LocaleManagerServicePackageMonitor extends PackageMonitor { } @Override public void onPackageAdded(String packageName, int uid) { mBackupHelper.onPackageAdded(packageName, uid); public void onPackageAddedWithExtras(String packageName, int uid, Bundle extras) { mBackupHelper.onPackageAddedWithExtras(packageName, uid, extras); } @Override Loading
services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java +66 −5 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; import android.os.HandlerThread; import android.os.LocaleList; import android.os.Process; Loading Loading @@ -488,7 +489,7 @@ public class LocaleManagerBackupRestoreTest { setUpPackageInstalled(pkgNameA); mPackageMonitor.onPackageAdded(pkgNameA, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(pkgNameA, DEFAULT_UID, new Bundle()); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameA, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsA), false, FrameworkStatsLog Loading @@ -504,7 +505,67 @@ public class LocaleManagerBackupRestoreTest { setUpPackageInstalled(pkgNameB); mPackageMonitor.onPackageAdded(pkgNameB, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(pkgNameB, DEFAULT_UID, new Bundle()); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameB, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsB), true, FrameworkStatsLog .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_BACKUP_RESTORE); mBackupHelper.persistLocalesModificationInfo(DEFAULT_USER_ID, pkgNameB, true, false); verify(mMockSpEditor, times(1)).putStringSet(Integer.toString(DEFAULT_USER_ID), new ArraySet<>(Arrays.asList(pkgNameB))); checkStageDataDoesNotExist(DEFAULT_USER_ID); } @Test public void testRestore_appInstalledAfterSUW_restoresFromStage_ArchiveEnabled() throws Exception { final ByteArrayOutputStream out = new ByteArrayOutputStream(); HashMap<String, LocalesInfo> pkgLocalesMap = new HashMap<>(); String pkgNameA = "com.android.myAppA"; String pkgNameB = "com.android.myAppB"; String langTagsA = "ru"; String langTagsB = "hi,fr"; LocalesInfo localesInfoA = new LocalesInfo(langTagsA, false); LocalesInfo localesInfoB = new LocalesInfo(langTagsB, true); pkgLocalesMap.put(pkgNameA, localesInfoA); pkgLocalesMap.put(pkgNameB, localesInfoB); writeTestPayload(out, pkgLocalesMap); setUpPackageNotInstalled(pkgNameA); setUpPackageNotInstalled(pkgNameB); setUpLocalesForPackage(pkgNameA, LocaleList.getEmptyLocaleList()); setUpLocalesForPackage(pkgNameB, LocaleList.getEmptyLocaleList()); setUpPackageNamesForSp(new ArraySet<>()); Bundle bundle = new Bundle(); bundle.putBoolean(Intent.EXTRA_ARCHIVAL, true); mPackageMonitor.onPackageAddedWithExtras(pkgNameA, DEFAULT_UID, bundle); mPackageMonitor.onPackageAddedWithExtras(pkgNameB, DEFAULT_UID, bundle); mBackupHelper.stageAndApplyRestoredPayload(out.toByteArray(), DEFAULT_USER_ID); verifyNothingRestored(); setUpPackageInstalled(pkgNameA); mPackageMonitor.onPackageUpdateFinished(pkgNameA, DEFAULT_UID); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameA, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsA), false, FrameworkStatsLog .APPLICATION_LOCALES_CHANGED__CALLER__CALLER_BACKUP_RESTORE); mBackupHelper.persistLocalesModificationInfo(DEFAULT_USER_ID, pkgNameA, false, false); verify(mMockSpEditor, times(0)).putStringSet(anyString(), any()); pkgLocalesMap.remove(pkgNameA); verifyStageDataForUser(pkgLocalesMap, DEFAULT_CREATION_TIME_MILLIS, DEFAULT_USER_ID); setUpPackageInstalled(pkgNameB); mPackageMonitor.onPackageUpdateFinished(pkgNameB, DEFAULT_UID); verify(mMockLocaleManagerService, times(1)).setApplicationLocales(pkgNameB, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsB), true, FrameworkStatsLog Loading Loading @@ -535,7 +596,7 @@ public class LocaleManagerBackupRestoreTest { setUpPackageInstalled(DEFAULT_PACKAGE_NAME); setUpLocalesForPackage(DEFAULT_PACKAGE_NAME, LocaleList.forLanguageTags("hi,mr")); mPackageMonitor.onPackageAdded(DEFAULT_PACKAGE_NAME, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(DEFAULT_PACKAGE_NAME, DEFAULT_UID, new Bundle()); // Since locales are already set, we should not restore anything for it. verifyNothingRestored(); Loading Loading @@ -612,7 +673,7 @@ public class LocaleManagerBackupRestoreTest { DEFAULT_CREATION_TIME_MILLIS + RETENTION_PERIOD.minusHours(1).toMillis()); setUpPackageInstalled(pkgNameA); mPackageMonitor.onPackageAdded(pkgNameA, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(pkgNameA, DEFAULT_UID, new Bundle()); verify(mMockLocaleManagerService, times(1)).setApplicationLocales( pkgNameA, DEFAULT_USER_ID, LocaleList.forLanguageTags(langTagsA), false, Loading @@ -627,7 +688,7 @@ public class LocaleManagerBackupRestoreTest { DEFAULT_CREATION_TIME_MILLIS + RETENTION_PERIOD.plusSeconds(1).toMillis()); setUpPackageInstalled(pkgNameB); mPackageMonitor.onPackageAdded(pkgNameB, DEFAULT_UID); mPackageMonitor.onPackageAddedWithExtras(pkgNameB, DEFAULT_UID, new Bundle()); verify(mMockLocaleManagerService, times(0)).setApplicationLocales(eq(pkgNameB), anyInt(), any(), anyBoolean(), anyInt()); Loading