Move PackageMonitorImpl to separate class for re-usability in locales
dir. Bug: 220076498 Test: atest CtsLocaleManagerTestCases Test: atest CtsBackupTestCases:AppLocalesBackupTest Test: atest FrameworksServicesTests:LocaleManagerServiceTest Test: atest FrameworksServicesTests:LocaleManagerBackupRestoreTest Change-Id: I54c59bd0a91598c8488979d824d94bfa3c5691e6
This commit is contained in:
@@ -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 {
|
||||
@@ -394,48 +426,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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
@@ -129,11 +143,6 @@ public class LocaleManagerService extends SystemService {
|
||||
return LocaleManagerService.this.getApplicationLocales(appPackageName, userId);
|
||||
}
|
||||
|
||||
@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,
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user