Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0992e8a authored by “Ankita's avatar “Ankita
Browse files

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
parent ddb497d6
Loading
Loading
Loading
Loading
+51 −61
Original line number Diff line number Diff line
@@ -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.
     *
+18 −17
Original line number Diff line number Diff line
@@ -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,
+49 −0
Original line number Diff line number Diff line
/*
 * 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();
    }
}
+10 −2
Original line number Diff line number Diff line
@@ -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);
    }

+6 −1
Original line number Diff line number Diff line
@@ -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)
Loading