diff options
6 files changed, 138 insertions, 83 deletions
diff --git a/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java b/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java index 01aee7bc1942..db81393a9ad6 100644 --- a/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java +++ b/services/core/java/com/android/server/locales/LocaleManagerBackupHelper.java @@ -34,7 +34,6 @@ import android.content.pm.PackageManagerInternal; import android.os.Binder; import android.os.HandlerThread; import android.os.LocaleList; -import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; @@ -45,7 +44,6 @@ import android.util.TypedXmlSerializer; import android.util.Xml; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.content.PackageMonitor; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; @@ -89,32 +87,24 @@ class LocaleManagerBackupHelper { // SparseArray because it is more memory-efficient than a HashMap. private final SparseArray<StagedData> mStagedData; - private final PackageMonitor mPackageMonitor; private final BroadcastReceiver mUserMonitor; LocaleManagerBackupHelper(LocaleManagerService localeManagerService, - PackageManagerInternal pmInternal) { + PackageManagerInternal pmInternal, HandlerThread broadcastHandlerThread) { this(localeManagerService.mContext, localeManagerService, pmInternal, Clock.systemUTC(), - new SparseArray<>()); + new SparseArray<>(), broadcastHandlerThread); } @VisibleForTesting LocaleManagerBackupHelper(Context context, LocaleManagerService localeManagerService, - PackageManagerInternal pmInternal, Clock clock, SparseArray<StagedData> stagedData) { + PackageManagerInternal pmInternal, Clock clock, SparseArray<StagedData> stagedData, + HandlerThread broadcastHandlerThread) { mContext = context; mLocaleManagerService = localeManagerService; mPackageManagerInternal = pmInternal; mClock = clock; mStagedData = stagedData; - HandlerThread broadcastHandlerThread = new HandlerThread(TAG, - Process.THREAD_PRIORITY_BACKGROUND); - broadcastHandlerThread.start(); - - mPackageMonitor = new PackageMonitorImpl(); - mPackageMonitor.register(context, broadcastHandlerThread.getLooper(), - UserHandle.ALL, - true); mUserMonitor = new UserMonitor(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_REMOVED); @@ -127,11 +117,6 @@ class LocaleManagerBackupHelper { return mUserMonitor; } - @VisibleForTesting - PackageMonitor getPackageMonitor() { - return mPackageMonitor; - } - /** * @see LocaleManagerInternal#getBackupPayload(int userId) */ @@ -267,6 +252,53 @@ class LocaleManagerBackupHelper { BackupManager.dataChanged(SYSTEM_BACKUP_PACKAGE_KEY); } + /** + * <p><b>Note:</b> This is invoked by service's common monitor + * {@link LocaleManagerServicePackageMonitor#onPackageAdded} 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); + } + } + } catch (Exception e) { + Slog.e(TAG, "Exception in onPackageAdded.", e); + } + } + + /** + * <p><b>Note:</b> This is invoked by service's common monitor + * {@link LocaleManagerServicePackageMonitor#onPackageDataCleared} when a package's data + * is cleared. + */ + void onPackageDataCleared() { + try { + notifyBackupManager(); + } catch (Exception e) { + Slog.e(TAG, "Exception in onPackageDataCleared.", e); + } + } + + /** + * <p><b>Note:</b> This is invoked by service's common monitor + * {@link LocaleManagerServicePackageMonitor#onPackageRemoved} when a package is removed + * from device. + */ + void onPackageRemoved() { + try { + notifyBackupManager(); + } catch (Exception e) { + Slog.e(TAG, "Exception in onPackageRemoved.", e); + } + } + private boolean isPackageInstalledForUser(String packageName, int userId) { PackageInfo pkgInfo = null; try { @@ -395,48 +427,6 @@ class LocaleManagerBackupHelper { } /** - * Helper to monitor package states. - * - * <p>We're interested in package added, package data cleared and package removed events. - */ - private final class PackageMonitorImpl extends PackageMonitor { - @Override - public 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); - } - } - } catch (Exception e) { - Slog.e(TAG, "Exception in onPackageAdded.", e); - } - } - - @Override - public void onPackageDataCleared(String packageName, int uid) { - try { - notifyBackupManager(); - } catch (Exception e) { - Slog.e(TAG, "Exception in onPackageDataCleared.", e); - } - } - - @Override - public void onPackageRemoved(String packageName, int uid) { - try { - notifyBackupManager(); - } catch (Exception e) { - Slog.e(TAG, "Exception in onPackageRemoved.", e); - } - } - } - - /** * Performs lazy restore from the staged data. * * <p>This is invoked by the package monitor on the package added callback. diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java index d459f8df99b6..c42770555bab 100644 --- a/services/core/java/com/android/server/locales/LocaleManagerService.java +++ b/services/core/java/com/android/server/locales/LocaleManagerService.java @@ -29,6 +29,7 @@ import android.content.Intent; 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.Process; import android.os.RemoteException; @@ -38,14 +39,13 @@ import android.os.UserHandle; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.DumpUtils; +import com.android.internal.content.PackageMonitor; import com.android.internal.util.FrameworkStatsLog; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.wm.ActivityTaskManagerInternal; import java.io.FileDescriptor; -import java.io.PrintWriter; /** * The implementation of ILocaleManager.aidl. @@ -62,6 +62,8 @@ public class LocaleManagerService extends SystemService { private LocaleManagerBackupHelper mBackupHelper; + private final PackageMonitor mPackageMonitor; + public static final boolean DEBUG = false; public LocaleManagerService(Context context) { @@ -71,15 +73,26 @@ public class LocaleManagerService extends SystemService { mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); + + HandlerThread broadcastHandlerThread = new HandlerThread(TAG, + Process.THREAD_PRIORITY_BACKGROUND); + broadcastHandlerThread.start(); + mBackupHelper = new LocaleManagerBackupHelper(this, - mPackageManagerInternal); + mPackageManagerInternal, broadcastHandlerThread); + + mPackageMonitor = new LocaleManagerServicePackageMonitor(mBackupHelper); + mPackageMonitor.register(context, broadcastHandlerThread.getLooper(), + UserHandle.ALL, + true); } @VisibleForTesting LocaleManagerService(Context context, ActivityTaskManagerInternal activityTaskManagerInternal, ActivityManagerInternal activityManagerInternal, PackageManagerInternal packageManagerInternal, - LocaleManagerBackupHelper localeManagerBackupHelper) { + LocaleManagerBackupHelper localeManagerBackupHelper, + PackageMonitor packageMonitor) { super(context); mContext = context; mBinderService = new LocaleManagerBinderService(); @@ -87,6 +100,7 @@ public class LocaleManagerService extends SystemService { mActivityManagerInternal = activityManagerInternal; mPackageManagerInternal = packageManagerInternal; mBackupHelper = localeManagerBackupHelper; + mPackageMonitor = packageMonitor; } @Override @@ -130,11 +144,6 @@ public class LocaleManagerService extends SystemService { } @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - LocaleManagerService.this.dump(fd, pw, args); - } - - @Override public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver) { @@ -407,14 +416,6 @@ public class LocaleManagerService extends SystemService { return null; } - /** - * Dumps useful info related to service. - */ - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; - // TODO(b/201766221): Implement when there is state. - } - private void logMetric(@NonNull AppLocaleChangedAtomRecord atomRecordForMetrics) { FrameworkStatsLog.write(FrameworkStatsLog.APPLICATION_LOCALES_CHANGED, atomRecordForMetrics.mCallingUid, diff --git a/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java b/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java new file mode 100644 index 000000000000..b459be768b9f --- /dev/null +++ b/services/core/java/com/android/server/locales/LocaleManagerServicePackageMonitor.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.locales; + +import com.android.internal.content.PackageMonitor; + +/** + * Helper to monitor package states inside {@link LocaleManagerService}. + * + * <p> These listeners forward the call to different aspects of locale service that + * handle the business logic. + * <p> We're interested in package added, package data cleared and package removed events. + */ +final class LocaleManagerServicePackageMonitor extends PackageMonitor { + private LocaleManagerBackupHelper mBackupHelper; + + LocaleManagerServicePackageMonitor(LocaleManagerBackupHelper localeManagerBackupHelper) { + mBackupHelper = localeManagerBackupHelper; + } + + @Override + public void onPackageAdded(String packageName, int uid) { + mBackupHelper.onPackageAdded(packageName, uid); + } + + @Override + public void onPackageDataCleared(String packageName, int uid) { + mBackupHelper.onPackageDataCleared(); + } + + @Override + public void onPackageRemoved(String packageName, int uid) { + mBackupHelper.onPackageRemoved(); + } +} 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 c77100045118..0287510041be 100644 --- a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java +++ b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerBackupRestoreTest.java @@ -41,7 +41,9 @@ 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.Process; import android.os.RemoteException; import android.os.SimpleClock; import android.util.SparseArray; @@ -78,6 +80,7 @@ import java.util.Map; */ @RunWith(AndroidJUnit4.class) public class LocaleManagerBackupRestoreTest { + private static final String TAG = "LocaleManagerBackupRestoreTest"; private static final String DEFAULT_PACKAGE_NAME = "com.android.myapp"; private static final String DEFAULT_LOCALE_TAGS = "en-XC,ar-XB"; private static final String TEST_LOCALES_XML_TAG = "locales"; @@ -131,12 +134,17 @@ public class LocaleManagerBackupRestoreTest { doReturn(mMockPackageManager).when(mMockContext).getPackageManager(); + HandlerThread broadcastHandlerThread = new HandlerThread(TAG, + Process.THREAD_PRIORITY_BACKGROUND); + broadcastHandlerThread.start(); + mBackupHelper = spy(new ShadowLocaleManagerBackupHelper(mMockContext, - mMockLocaleManagerService, mMockPackageManagerInternal, mClock, STAGE_DATA)); + mMockLocaleManagerService, mMockPackageManagerInternal, mClock, STAGE_DATA, + broadcastHandlerThread)); doNothing().when(mBackupHelper).notifyBackupManager(); mUserMonitor = mBackupHelper.getUserMonitor(); - mPackageMonitor = mBackupHelper.getPackageMonitor(); + mPackageMonitor = new LocaleManagerServicePackageMonitor(mBackupHelper); setCurrentTimeMillis(DEFAULT_CREATION_TIME_MILLIS); } 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 ca5b0cb1112f..0b3ef4542cbf 100644 --- a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java @@ -46,6 +46,7 @@ import android.os.LocaleList; import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.android.internal.content.PackageMonitor; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal.PackageConfig; @@ -86,6 +87,8 @@ public class LocaleManagerServiceTest { private ActivityTaskManagerInternal mMockActivityTaskManager; @Mock private ActivityManagerInternal mMockActivityManager; + @Mock + PackageMonitor mMockPackageMonitor; @Before public void setUp() throws Exception { @@ -93,6 +96,7 @@ public class LocaleManagerServiceTest { mMockActivityTaskManager = mock(ActivityTaskManagerInternal.class); mMockActivityManager = mock(ActivityManagerInternal.class); mMockPackageManagerInternal = mock(PackageManagerInternal.class); + mMockPackageMonitor = mock(PackageMonitor.class); // For unit tests, set the default installer info PackageManager mockPackageManager = mock(PackageManager.class); @@ -113,7 +117,8 @@ public class LocaleManagerServiceTest { mMockBackupHelper = mock(ShadowLocaleManagerBackupHelper.class); mLocaleManagerService = new LocaleManagerService(mMockContext, mMockActivityTaskManager, - mMockActivityManager, mMockPackageManagerInternal, mMockBackupHelper); + mMockActivityManager, mMockPackageManagerInternal, + mMockBackupHelper, mMockPackageMonitor); } @Test(expected = SecurityException.class) diff --git a/services/tests/servicestests/src/com/android/server/locales/ShadowLocaleManagerBackupHelper.java b/services/tests/servicestests/src/com/android/server/locales/ShadowLocaleManagerBackupHelper.java index b0fc6363b701..ad9be0d5fe8d 100644 --- a/services/tests/servicestests/src/com/android/server/locales/ShadowLocaleManagerBackupHelper.java +++ b/services/tests/servicestests/src/com/android/server/locales/ShadowLocaleManagerBackupHelper.java @@ -18,6 +18,7 @@ package com.android.server.locales; import android.content.Context; import android.content.pm.PackageManagerInternal; +import android.os.HandlerThread; import android.util.SparseArray; import java.time.Clock; @@ -31,7 +32,8 @@ public class ShadowLocaleManagerBackupHelper extends LocaleManagerBackupHelper { ShadowLocaleManagerBackupHelper(Context context, LocaleManagerService localeManagerService, PackageManagerInternal pmInternal, Clock clock, - SparseArray<LocaleManagerBackupHelper.StagedData> stagedData) { - super(context, localeManagerService, pmInternal, clock, stagedData); + SparseArray<LocaleManagerBackupHelper.StagedData> stagedData, + HandlerThread broadcastHandlerThread) { + super(context, localeManagerService, pmInternal, clock, stagedData, broadcastHandlerThread); } } |