diff options
| author | 2024-05-10 13:32:58 +0000 | |
|---|---|---|
| committer | 2024-05-10 13:32:58 +0000 | |
| commit | 83dd2e6881b51faad1e6340417342059bba7c50c (patch) | |
| tree | 22ee6abd2622b1d85aef29f6ecf22c8a6c106817 | |
| parent | a65fd3def3bb6046e3bcd93452ea7e1aae58cecb (diff) | |
| parent | db2b8f9fce9a77ae0ec94e25c388522e21af8fdb (diff) | |
Merge "[Panlingual] Restore per-app locales for an archived application" into main
3 files changed, 110 insertions, 20 deletions
diff --git a/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java b/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java index 0049213cbf55..d932bd4e6d20 100644 --- a/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java +++ b/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java @@ -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; @@ -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) { @@ -119,6 +125,7 @@ class LocaleManagerBackupHelper { mStagedData = stagedData; mDelegateAppLocalePackages = delegateAppLocalePackages != null ? delegateAppLocalePackages : createPersistedInfo(); + mPkgsToRestore = new ArraySet<>(); mUserMonitor = new UserMonitor(); IntentFilter filter = new IntentFilter(); @@ -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 { @@ -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); } /** @@ -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); } @@ -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 { diff --git a/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java b/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java index ecd3614b4ff4..e0a050fbf157 100644 --- a/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java +++ b/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java @@ -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; @@ -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 diff --git a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java index 40ecaf1770a9..7dd1847114c8 100644 --- a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java +++ b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java @@ -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; @@ -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 @@ -504,7 +505,7 @@ 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 @@ -518,6 +519,66 @@ public class LocaleManagerBackupRestoreTest { } @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 + .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_appInstalledAfterSUWAndLocalesAlreadySet_restoresNothing() throws Exception { final ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -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(); @@ -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, @@ -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()); |