Merge "Move PackageMonitorImpl to separate class for re-usability in locales dir." into tm-dev

This commit is contained in:
TreeHugger Robot
2022-02-23 10:06:54 +00:00
committed by Android (Google) Code Review
6 changed files with 138 additions and 83 deletions

View File

@@ -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.
*

View File

@@ -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,

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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);
}
}