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

Commit af10dd15 authored by Joanne Chung's avatar Joanne Chung Committed by Android (Google) Code Review
Browse files

Merge "PackageMonitor improvement"

parents 989cca68 f7288456
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -3918,4 +3919,24 @@ public class ApplicationPackageManager extends PackageManager {
            throw e.rethrowFromSystemServer();
        }
    }

    @Override
    public void registerPackageMonitorCallback(@NonNull IRemoteCallback callback, int userId) {
        Objects.requireNonNull(callback);
        try {
            mPM.registerPackageMonitorCallback(callback, userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @Override
    public void unregisterPackageMonitorCallback(@NonNull IRemoteCallback callback) {
        Objects.requireNonNull(callback);
        try {
            mPM.unregisterPackageMonitorCallback(callback);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.content.pm.dex.IArtManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.content.IntentSender;
@@ -818,4 +819,8 @@ interface IPackageManager {
    boolean[] canPackageQuery(String sourcePackageName, in String[] targetPackageNames, int userId);

    boolean waitForHandler(long timeoutMillis, boolean forBackgroundHandler);

    void registerPackageMonitorCallback(IRemoteCallback callback, int userId);

    void unregisterPackageMonitorCallback(IRemoteCallback callback);
}
+32 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -2575,6 +2576,13 @@ public abstract class PackageManager {
    /** {@hide} */
    public static final String EXTRA_MOVE_ID = "android.content.pm.extra.MOVE_ID";

    /**
     * Extra field name for notifying package change event. Currently, it is used by PackageMonitor.
     * @hide
     */
    public static final String EXTRA_PACKAGE_MONITOR_CALLBACK_RESULT =
            "android.content.pm.extra.EXTRA_PACKAGE_MONITOR_CALLBACK_RESULT";

    /**
     * Usable by the required verifier as the {@code verificationCode} argument
     * for {@link PackageManager#verifyPendingInstall} to indicate that it will
@@ -11039,4 +11047,28 @@ public abstract class PackageManager {
        throw new UnsupportedOperationException(
                "relinquishUpdateOwnership not implemented in subclass");
    }

    /**
     * Register for notifications of package changes such as install, removal and other events.
     *
     * @param callback the callback to register for receiving the change events
     * @param userId The id of registered user
     * @hide
     */
    public void registerPackageMonitorCallback(@NonNull IRemoteCallback callback, int userId) {
        throw new UnsupportedOperationException(
                "registerPackageMonitorCallback not implemented in subclass");
    }

    /**
     * Unregister for notifications of package changes such as install, removal and other events.
     *
     * @param callback the callback to unregister for receiving the change events
     * @see #registerPackageMonitorCallback(IRemoteCallback, int)
     * @hide
     */
    public void unregisterPackageMonitorCallback(@NonNull IRemoteCallback callback) {
        throw new UnsupportedOperationException(
                "unregisterPackageMonitorCallback not implemented in subclass");
    }
}
+71 −26
Original line number Diff line number Diff line
@@ -22,15 +22,22 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IRemoteCallback;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;

import com.android.internal.os.BackgroundThread;

import java.util.Objects;
import java.util.concurrent.Executor;

/**
 * Helper class for monitoring the state of packages: adding, removing,
@@ -41,7 +48,6 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {

    final IntentFilter mPackageFilt;
    final IntentFilter mNonDataFilt;
    final IntentFilter mExternalFilt;

    Context mRegisteredContext;
    Handler mRegisteredHandler;
@@ -55,15 +61,16 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {

    String[] mTempArray = new String[1];

    PackageMonitorCallback mPackageMonitorCallback;

    @UnsupportedAppUsage
    public PackageMonitor() {
        final boolean isCore = UserHandle.isCore(android.os.Process.myUid());

        mPackageFilt = new IntentFilter();
        mPackageFilt.addAction(Intent.ACTION_PACKAGE_ADDED);
        mPackageFilt.addAction(Intent.ACTION_PACKAGE_REMOVED);
        mPackageFilt.addAction(Intent.ACTION_PACKAGE_CHANGED);
        // Settings app sends the broadcast
        mPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
        // AMS sends the broadcast
        mPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED);
        mPackageFilt.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
        mPackageFilt.addDataScheme("package");
@@ -72,20 +79,11 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
        }

        mNonDataFilt = new IntentFilter();
        mNonDataFilt.addAction(Intent.ACTION_UID_REMOVED);
        // UserController sends the broadcast
        mNonDataFilt.addAction(Intent.ACTION_USER_STOPPED);
        mNonDataFilt.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
        mNonDataFilt.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
        if (isCore) {
            mNonDataFilt.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        }

        mExternalFilt = new IntentFilter();
        mExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
        mExternalFilt.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
        if (isCore) {
            mExternalFilt.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        }
    }

    @UnsupportedAppUsage
@@ -102,6 +100,15 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {

    public void register(Context context, UserHandle user,
            boolean externalStorage, Handler handler) {
        // Remove until all using code are updated to new method.
        register(context, user, handler);
    }


    /**
     * Register for notifications of package changes such as install, removal and other events.
     */
    public void register(Context context, UserHandle user, Handler handler) {
        if (mRegisteredContext != null) {
            throw new IllegalStateException("Already registered");
        }
@@ -110,15 +117,17 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
        if (user != null) {
            context.registerReceiverAsUser(this, user, mPackageFilt, null, mRegisteredHandler);
            context.registerReceiverAsUser(this, user, mNonDataFilt, null, mRegisteredHandler);
            if (externalStorage) {
                context.registerReceiverAsUser(this, user, mExternalFilt, null,
                        mRegisteredHandler);
            }
        } else {
            context.registerReceiver(this, mPackageFilt, null, mRegisteredHandler);
            context.registerReceiver(this, mNonDataFilt, null, mRegisteredHandler);
            if (externalStorage) {
                context.registerReceiver(this, mExternalFilt, null, mRegisteredHandler);
        }
        if (mPackageMonitorCallback == null) {
            PackageManager pm = mRegisteredContext.getPackageManager();
            if (pm != null) {
                mPackageMonitorCallback = new PackageMonitorCallback(this,
                        new HandlerExecutor(mRegisteredHandler));
                int userId = user != null ? user.getIdentifier() : mRegisteredContext.getUserId();
                pm.registerPackageMonitorCallback(mPackageMonitorCallback, userId);
            }
        }
    }
@@ -133,6 +142,12 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
            throw new IllegalStateException("Not registered");
        }
        mRegisteredContext.unregisterReceiver(this);

        PackageManager pm = mRegisteredContext.getPackageManager();
        if (pm != null && mPackageMonitorCallback != null) {
            pm.unregisterPackageMonitorCallback(mPackageMonitorCallback);
        }
        mPackageMonitorCallback = null;
        mRegisteredContext = null;
    }

@@ -330,6 +345,10 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        doHandlePackageEvent(intent);
    }

    private void doHandlePackageEvent(Intent intent) {
        mChangeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                UserHandle.USER_NULL);
        if (mChangeUserId == UserHandle.USER_NULL) {
@@ -465,4 +484,30 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
        onFinishPackageChanges();
        mChangeUserId = UserHandle.USER_NULL;
    }

    private static final class PackageMonitorCallback extends IRemoteCallback.Stub {

        private final PackageMonitor mPackageMonitor;
        private final Executor mExecutor;

        PackageMonitorCallback(PackageMonitor monitor, Executor executor) {
            mPackageMonitor = monitor;
            mExecutor = executor;
        }

        @Override
        public void sendResult(Bundle data) throws RemoteException {
            onHandlePackageMonitorCallback(data);
        }

        private void onHandlePackageMonitorCallback(Bundle bundle) {
            Intent intent = bundle.getParcelable(
                    PackageManager.EXTRA_PACKAGE_MONITOR_CALLBACK_RESULT, Intent.class);
            if (intent == null) {
                Log.w(TAG, "No intent is set for PackageMonitorCallback");
                return;
            }
            mExecutor.execute(() -> mPackageMonitor.doHandlePackageEvent(intent));
        }
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.controls.controller

import android.content.Context
import android.content.pm.PackageManager
import android.os.Handler
import android.os.UserHandle
import android.testing.AndroidTestingRunner
@@ -34,6 +35,7 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations

@SmallTest
@@ -42,12 +44,14 @@ class PackageUpdateMonitorTest : SysuiTestCase() {

    @Mock private lateinit var context: Context
    @Mock private lateinit var bgHandler: Handler
    @Mock private lateinit var packageManager: PackageManager

    private lateinit var underTest: PackageUpdateMonitor

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)
        whenever(context.packageManager).thenReturn(packageManager)
    }

    @Test
@@ -58,9 +62,16 @@ class PackageUpdateMonitorTest : SysuiTestCase() {
        // There are two receivers registered
        verify(context, times(2))
            .registerReceiverAsUser(any(), eq(USER), any(), eq(null), eq(bgHandler))
        verify(packageManager).registerPackageMonitorCallback(any(), eq(USER.getIdentifier()))
        // context will be used to get PackageManager, the test should clear invocations
        // for next startMonitoring() assertion
        clearInvocations(context)

        underTest.startMonitoring()
        // No more interactions for registerReceiverAsUser
        verifyNoMoreInteractions(context)
        // No more interactions for registerPackageMonitorCallback
        verifyNoMoreInteractions(packageManager)
    }

    @Test
@@ -69,12 +80,20 @@ class PackageUpdateMonitorTest : SysuiTestCase() {

        underTest.startMonitoring()
        clearInvocations(context)
        clearInvocations(packageManager)

        underTest.stopMonitoring()
        verify(context).unregisterReceiver(any())
        verify(packageManager).unregisterPackageMonitorCallback(any())
        // context will be used to get PackageManager, the test should clear invocations
        // for next stopMonitoring() assertion
        clearInvocations(context)

        underTest.stopMonitoring()
        // No more interactions for unregisterReceiver
        verifyNoMoreInteractions(context)
        // No more interactions for unregisterPackageMonitorCallback
        verifyNoMoreInteractions(packageManager)
    }

    @Test
Loading