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

Commit 4246ac6f authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka Committed by Android (Google) Code Review
Browse files

Merge "Fix BroadcastReceiver leakage"

parents 4905888b edbe4047
Loading
Loading
Loading
Loading
+17 −34
Original line number Diff line number Diff line
@@ -62,8 +62,9 @@ public final class DynamicIndexableContentMonitor implements
    // Shorten the class name because log TAG can be at most 23 chars.
    private static final String TAG = "DynamicContentMonitor";

    @VisibleForTesting
    static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000;
    private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000;
    // A PackageMonitor shared among Settings activities.
    private static final PackageChangeMonitor PACKAGE_CHANGE_MONITOR = new PackageChangeMonitor();

    // Null if not initialized.
    @Nullable private Index mIndex;
@@ -87,7 +88,8 @@ public final class DynamicIndexableContentMonitor implements
    @VisibleForTesting
    static void resetForTesting() {
        InputDevicesMonitor.getInstance().resetForTesting();
        PackageChangeMonitor.getInstance().resetForTesting();
        AccessibilityServicesMonitor.getInstance().resetForTesting();
        InputMethodServicesMonitor.getInstance().resetForTesting();
    }

    /**
@@ -123,20 +125,23 @@ public final class DynamicIndexableContentMonitor implements
            Log.w(TAG, "Skipping content monitoring because user is locked");
            return;
        }
        mContext = activity;
        final Context context = activity.getApplicationContext();
        mContext = context;
        mIndex = index;

        mHasFeaturePrinting = mContext.getPackageManager()
        PACKAGE_CHANGE_MONITOR.register(context);
        mHasFeaturePrinting = context.getPackageManager()
                .hasSystemFeature(PackageManager.FEATURE_PRINTING);
        if (mHasFeaturePrinting) {
            activity.getLoaderManager().initLoader(loaderId, null /* args */, this /* callbacks */);
        }

        // Watch for input device changes.
        InputDevicesMonitor.getInstance().initialize(mContext, mIndex);
        InputDevicesMonitor.getInstance().initialize(context, index);

        // Start tracking packages.
        PackageChangeMonitor.getInstance().initialize(mContext, mIndex);
        AccessibilityServicesMonitor.getInstance().initialize(context, index);
        InputMethodServicesMonitor.getInstance().initialize(context, index);
    }

    /**
@@ -149,6 +154,7 @@ public final class DynamicIndexableContentMonitor implements
    public void unregister(Activity activity, int loaderId) {
        if (mIndex == null) return;

        PACKAGE_CHANGE_MONITOR.unregister();
        if (mHasFeaturePrinting) {
            activity.getLoaderManager().destroyLoader(loaderId);
        }
@@ -237,33 +243,9 @@ public final class DynamicIndexableContentMonitor implements
        // Null if not initialized.
        @Nullable private PackageManager mPackageManager;

        private PackageChangeMonitor() {}

        private static class SingletonHolder {
            private static final PackageChangeMonitor INSTANCE = new PackageChangeMonitor();
        }

        static PackageChangeMonitor getInstance() {
            return SingletonHolder.INSTANCE;
        }

        @VisibleForTesting
        synchronized void resetForTesting() {
            if (mPackageManager != null) {
                unregister();
            }
            mPackageManager = null;
            AccessibilityServicesMonitor.getInstance().resetForTesting();
            InputMethodServicesMonitor.getInstance().resetForTesting();
        }

        synchronized void initialize(Context context, Index index) {
            if (mPackageManager != null) return;;
        public void register(Context context) {
            mPackageManager = context.getPackageManager();

            AccessibilityServicesMonitor.getInstance().initialize(context, index);
            InputMethodServicesMonitor.getInstance().initialize(context, index);

            // Start tracking packages. Use background thread for monitoring. Note that no need to
            // unregister this monitor. This should be alive while Settings app is running.
            register(context, null /* thread */, UserHandle.CURRENT, false);
@@ -271,13 +253,13 @@ public final class DynamicIndexableContentMonitor implements

        // Covers installed, appeared external storage with the package, upgraded.
        @Override
        public void onPackageAppeared(String packageName, int uid) {
        public void onPackageAppeared(String packageName, int reason) {
            postPackageAvailable(packageName);
        }

        // Covers uninstalled, removed external storage with the package.
        @Override
        public void onPackageDisappeared(String packageName, int uid) {
        public void onPackageDisappeared(String packageName, int reason) {
            postPackageUnavailable(packageName);
        }

@@ -440,6 +422,7 @@ public final class DynamicIndexableContentMonitor implements
                }
            }

            // TODO: Implements by JobScheduler with TriggerContentUri parameters.
            // Watch for related content URIs.
            mContentResolver.registerContentObserver(UserDictionary.Words.CONTENT_URI,
                    true /* notifyForDescendants */, this /* observer */);
+52 −43
Original line number Diff line number Diff line
@@ -102,7 +102,6 @@ import java.util.List;
)
public class DynamicIndexableContentMonitorTest {

    private static final int USER_ID = 5678;
    private static final int LOADER_ID = 1234;
    private static final String A11Y_PACKAGE_1 = "a11y-1";
    private static final String A11Y_PACKAGE_2 = "a11y-2";
@@ -151,6 +150,10 @@ public class DynamicIndexableContentMonitorTest {

    @After
    public void shutDown() {
        mMonitor.unregister(mActivity, LOADER_ID);
        // BroadcastReceiver must be unregistered.
        assertThat(extractPackageMonitor()).isNull();

        DynamicIndexableContentMonitor.resetForTesting();
        mRobolectricPackageManager.reset();
    }
@@ -187,6 +190,11 @@ public class DynamicIndexableContentMonitorTest {

        // No destroy loader should happen.
        verify(mLoaderManager, never()).destroyLoader(anyInt());
        // BroadcastReceiver must be unregistered.
        assertThat(extractPackageMonitor()).isNull();

        // To suppress spurious test fail in {@link #shutDown()}.
        mMonitor.register(mActivity, LOADER_ID, mIndex, true /* isUserUnlocked */);
    }

    @Test
@@ -220,6 +228,7 @@ public class DynamicIndexableContentMonitorTest {
        /*
         * Nothing happens on successive register calls.
         */
        mMonitor.unregister(mActivity, LOADER_ID);
        reset(mIndex);

        mMonitor.register(mActivity, LOADER_ID, mIndex, true /* isUserUnlocked */);
@@ -259,74 +268,59 @@ public class DynamicIndexableContentMonitorTest {
    public void testAccessibilityServicesMonitor() throws Exception {
        mMonitor.register(mActivity, LOADER_ID, mIndex, true /* isUserUnlocked */);

        final PackageMonitor packageMonitor = extractPackageMonitor();
        assertThat(packageMonitor).isNotNull();

        verifyRebuildIndexing(AccessibilitySettings.class);

        /*
         * When an accessibility service package is installed, incremental indexing happen.
         */
        installAccessibilityService(A11Y_PACKAGE_1);
        reset(mIndex);

        packageMonitor.onPackageAppeared(A11Y_PACKAGE_1, USER_ID);
        Robolectric.flushBackgroundThreadScheduler();
        installAccessibilityService(A11Y_PACKAGE_1);

        verifyIncrementalIndexing(AccessibilitySettings.class);

        /*
         * When another accessibility service package is installed, incremental indexing happens.
         */
        installAccessibilityService(A11Y_PACKAGE_2);
        reset(mIndex);

        packageMonitor.onPackageAppeared(A11Y_PACKAGE_2, USER_ID);
        Robolectric.flushBackgroundThreadScheduler();
        installAccessibilityService(A11Y_PACKAGE_2);

        verifyIncrementalIndexing(AccessibilitySettings.class);

        /*
         * When an accessibility service is disabled, rebuild indexing happens.
         */
        ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
                A11Y_PACKAGE_1, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0 /* flags */);
        reset(mIndex);

        packageMonitor.onPackageModified(A11Y_PACKAGE_1);
        Robolectric.flushBackgroundThreadScheduler();
        disableInstalledPackage(A11Y_PACKAGE_1);

        verifyRebuildIndexing(AccessibilitySettings.class);

        /*
         * When an accessibility service is enabled, incremental indexing happens.
         */
        ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
                A11Y_PACKAGE_1, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
        reset(mIndex);

        packageMonitor.onPackageModified(A11Y_PACKAGE_1);
        Robolectric.flushBackgroundThreadScheduler();
        enableInstalledPackage(A11Y_PACKAGE_1);

        verifyIncrementalIndexing(AccessibilitySettings.class);

        /*
         * When an accessibility service package is uninstalled, rebuild indexing happens.
         */
        uninstallAccessibilityService(A11Y_PACKAGE_1);
        reset(mIndex);

        packageMonitor.onPackageDisappeared(A11Y_PACKAGE_1, USER_ID);
        uninstallAccessibilityService(A11Y_PACKAGE_1);

        verifyRebuildIndexing(AccessibilitySettings.class);

        /*
         * When an input method service package is installed, nothing happens.
         */
        installInputMethodService(IME_PACKAGE_1);
        reset(mIndex);

        packageMonitor.onPackageAppeared(IME_PACKAGE_1, USER_ID);
        installInputMethodService(IME_PACKAGE_1);

        verifyNoIndexing(AccessibilitySettings.class);
    }
@@ -335,9 +329,6 @@ public class DynamicIndexableContentMonitorTest {
    public void testInputMethodServicesMonitor() throws Exception {
        mMonitor.register(mActivity, LOADER_ID, mIndex, true /* isUserUnlocked */);

        final PackageMonitor packageMonitor = extractPackageMonitor();
        assertThat(packageMonitor).isNotNull();

        verifyRebuildIndexing(VirtualKeyboardFragment.class);
        verifyRebuildIndexing(AvailableVirtualKeyboardFragment.class);

@@ -350,11 +341,9 @@ public class DynamicIndexableContentMonitorTest {
        /*
         * When an input method service package is installed, incremental indexing happen.
         */
        installInputMethodService(IME_PACKAGE_1);
        reset(mIndex);

        packageMonitor.onPackageAppeared(IME_PACKAGE_1, USER_ID);
        Robolectric.flushBackgroundThreadScheduler();
        installInputMethodService(IME_PACKAGE_1);

        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
@@ -362,11 +351,9 @@ public class DynamicIndexableContentMonitorTest {
        /*
         * When another input method service package is installed, incremental indexing happens.
         */
        installInputMethodService(IME_PACKAGE_2);
        reset(mIndex);

        packageMonitor.onPackageAppeared(IME_PACKAGE_2, USER_ID);
        Robolectric.flushBackgroundThreadScheduler();
        installInputMethodService(IME_PACKAGE_2);

        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
@@ -374,12 +361,9 @@ public class DynamicIndexableContentMonitorTest {
        /*
         * When an input method service is disabled, rebuild indexing happens.
         */
        ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
                IME_PACKAGE_1, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0 /* flags */);
        reset(mIndex);

        packageMonitor.onPackageModified(IME_PACKAGE_1);
        Robolectric.flushBackgroundThreadScheduler();
        disableInstalledPackage(IME_PACKAGE_1);

        verifyRebuildIndexing(VirtualKeyboardFragment.class);
        verifyRebuildIndexing(AvailableVirtualKeyboardFragment.class);
@@ -387,12 +371,9 @@ public class DynamicIndexableContentMonitorTest {
        /*
         * When an input method service is enabled, incremental indexing happens.
         */
        ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
                IME_PACKAGE_1, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
        reset(mIndex);

        packageMonitor.onPackageModified(IME_PACKAGE_1);
        Robolectric.flushBackgroundThreadScheduler();
        enableInstalledPackage(IME_PACKAGE_1);

        verifyIncrementalIndexing(VirtualKeyboardFragment.class);
        verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
@@ -400,10 +381,9 @@ public class DynamicIndexableContentMonitorTest {
        /*
         * When an input method service package is uninstalled, rebuild indexing happens.
         */
        uninstallInputMethodService(IME_PACKAGE_1);
        reset(mIndex);

        packageMonitor.onPackageDisappeared(IME_PACKAGE_1, USER_ID);
        uninstallInputMethodService(IME_PACKAGE_1);

        verifyRebuildIndexing(VirtualKeyboardFragment.class);
        verifyRebuildIndexing(AvailableVirtualKeyboardFragment.class);
@@ -411,10 +391,9 @@ public class DynamicIndexableContentMonitorTest {
        /*
         * When an accessibility service package is installed, nothing happens.
         */
        installAccessibilityService(A11Y_PACKAGE_1);
        reset(mIndex);

        packageMonitor.onPackageAppeared(A11Y_PACKAGE_1, USER_ID);
        installAccessibilityService(A11Y_PACKAGE_1);

        verifyNoIndexing(VirtualKeyboardFragment.class);
        verifyNoIndexing(AvailableVirtualKeyboardFragment.class);
@@ -528,6 +507,20 @@ public class DynamicIndexableContentMonitorTest {
        return contentObserver;
    }

    private void enableInstalledPackage(String packageName) {
        ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
                packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
        extractPackageMonitor().onPackageModified(packageName);
        Robolectric.flushBackgroundThreadScheduler();
    }

    private void disableInstalledPackage(String packageName) {
        ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
                packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0 /* flags */);
        extractPackageMonitor().onPackageModified(packageName);
        Robolectric.flushBackgroundThreadScheduler();
    }

    private void installAccessibilityService(String packageName) throws Exception {
        final AccessibilityServiceInfo serviceToAdd = buildAccessibilityServiceInfo(packageName);

@@ -540,6 +533,10 @@ public class DynamicIndexableContentMonitorTest {
                .getAccessibilityServiceIntent(packageName);
        mRobolectricPackageManager.addResolveInfoForIntent(intent, serviceToAdd.getResolveInfo());
        mRobolectricPackageManager.addPackage(packageName);

        extractPackageMonitor()
                .onPackageAppeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
        Robolectric.flushBackgroundThreadScheduler();
    }

    private void uninstallAccessibilityService(String packageName) throws Exception {
@@ -554,6 +551,10 @@ public class DynamicIndexableContentMonitorTest {
                .getAccessibilityServiceIntent(packageName);
        mRobolectricPackageManager.removeResolveInfosForIntent(intent, packageName);
        mRobolectricPackageManager.removePackage(packageName);

        extractPackageMonitor()
                .onPackageDisappeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
        Robolectric.flushBackgroundThreadScheduler();
    }

    private void installInputMethodService(String packageName) throws Exception {
@@ -568,6 +569,10 @@ public class DynamicIndexableContentMonitorTest {
        final Intent intent = DynamicIndexableContentMonitor.getIMEServiceIntent(packageName);
        mRobolectricPackageManager.addResolveInfoForIntent(intent, resolveInfoToAdd);
        mRobolectricPackageManager.addPackage(packageName);

        extractPackageMonitor()
                .onPackageAppeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
        Robolectric.flushBackgroundThreadScheduler();
    }

    private void uninstallInputMethodService(String packageName) throws Exception {
@@ -582,6 +587,10 @@ public class DynamicIndexableContentMonitorTest {
        final Intent intent = DynamicIndexableContentMonitor.getIMEServiceIntent(packageName);
        mRobolectricPackageManager.removeResolveInfosForIntent(intent, packageName);
        mRobolectricPackageManager.removePackage(packageName);

        extractPackageMonitor()
                .onPackageDisappeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
        Robolectric.flushBackgroundThreadScheduler();
    }

    private AccessibilityServiceInfo buildAccessibilityServiceInfo(String packageName)