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

Commit 305f8834 authored by Hall Liu's avatar Hall Liu Committed by android-build-merger
Browse files

Merge changes from topic "fix-package-manager-usages"

am: 7ecda750

Change-Id: I3d3de1578520ce9dc0a5380a1d0f1b8fb343d2f7
parents aff6974b 7ecda750
Loading
Loading
Loading
Loading
+19 −15
Original line number Diff line number Diff line
@@ -24,17 +24,17 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.UserHandle;

import com.android.internal.os.BackgroundThread;

/**
 * Helper class for monitoring the state of packages: adding, removing,
 * updating, and disappearing and reappearing on the SD card.
 */
public abstract class PackageChangeReceiver extends BroadcastReceiver {
    static final IntentFilter sPackageIntentFilter = new IntentFilter();
    private static HandlerThread sHandlerThread;
    static {
        sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -43,28 +43,24 @@ public abstract class PackageChangeReceiver extends BroadcastReceiver {
        sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
        sPackageIntentFilter.addDataScheme("package");
    }
    // Keep an instance of Context around as long as we still want the receiver:
    // if the instance of Context gets garbage-collected, it'll unregister the receiver, so only
    // unset when we want to unregister.
    Context mRegisteredContext;

    /**
     * To register the intents that needed for monitoring the state of packages
     * To register the intents that needed for monitoring the state of packages. Once this method
     * has been called on an instance of {@link PackageChangeReceiver}, all subsequent calls must
     * have the same {@code user} argument.
     */
    public void register(@NonNull Context context, @Nullable Looper thread,
            @Nullable UserHandle user) {
        if (mRegisteredContext != null) {
            throw new IllegalStateException("Already registered");
        }
        Handler handler = (thread == null) ? BackgroundThread.getHandler() : new Handler(thread);
        mRegisteredContext = context;
        if (handler != null) {
            if (user != null) {
                context.registerReceiverAsUser(this, user, sPackageIntentFilter, null, handler);
            } else {
                context.registerReceiver(this, sPackageIntentFilter,
                        null, handler);
            }
        } else {
            throw new NullPointerException();
        }
        Handler handler = new Handler(thread == null ? getStaticLooper() : thread);
        mRegisteredContext = user == null ? context : context.createContextAsUser(user, 0);
        mRegisteredContext.registerReceiver(this, sPackageIntentFilter, null, handler);
    }

    /**
@@ -78,6 +74,14 @@ public abstract class PackageChangeReceiver extends BroadcastReceiver {
        mRegisteredContext = null;
    }

    private static synchronized Looper getStaticLooper() {
        if (sHandlerThread == null) {
            sHandlerThread = new HandlerThread(PackageChangeReceiver.class.getSimpleName());
            sHandlerThread.start();
        }
        return sHandlerThread.getLooper();
    }

    /**
     * This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
     */
+35 −31
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;

import java.util.stream.Collectors;


/**
@@ -250,6 +250,7 @@ public final class SmsApplication {
    private static Collection<SmsApplicationData> getApplicationCollectionInternal(
            Context context, int userId) {
        PackageManager packageManager = context.getPackageManager();
        UserHandle userHandle = UserHandle.of(userId);

        // Get the list of apps registered for SMS
        Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
@@ -258,7 +259,7 @@ public final class SmsApplication {
        }
        List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
                PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                userId);
                userHandle);

        HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();

@@ -285,7 +286,7 @@ public final class SmsApplication {
        intent.setDataAndType(null, "application/vnd.wap.mms-message");
        List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
                PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                userId);
                userHandle);
        for (ResolveInfo resolveInfo : mmsReceivers) {
            final ActivityInfo activityInfo = resolveInfo.activityInfo;
            if (activityInfo == null) {
@@ -327,7 +328,7 @@ public final class SmsApplication {
                Uri.fromParts(SCHEME_SMSTO, "", null));
        List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent,
                PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                userId);
                userHandle);
        for (ResolveInfo resolveInfo : sendToActivities) {
            final ActivityInfo activityInfo = resolveInfo.activityInfo;
            if (activityInfo == null) {
@@ -345,7 +346,7 @@ public final class SmsApplication {
        List<ResolveInfo> smsAppChangedReceivers =
                packageManager.queryBroadcastReceiversAsUser(intent,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
        if (DEBUG_MULTIUSER) {
            Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
                    smsAppChangedReceivers);
@@ -372,7 +373,7 @@ public final class SmsApplication {
        List<ResolveInfo> providerChangedReceivers =
                packageManager.queryBroadcastReceiversAsUser(intent,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
        if (DEBUG_MULTIUSER) {
            Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
                    providerChangedReceivers);
@@ -399,7 +400,7 @@ public final class SmsApplication {
        List<ResolveInfo> simFullReceivers =
                packageManager.queryBroadcastReceiversAsUser(intent,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
        if (DEBUG_MULTIUSER) {
            Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
                    + simFullReceivers);
@@ -631,7 +632,8 @@ public final class SmsApplication {
        }

        // We only make the change if the new package is valid
        PackageManager packageManager = context.getPackageManager();
        PackageManager packageManager =
                context.createContextAsUser(userHandle, 0).getPackageManager();
        Collection<SmsApplicationData> applications = getApplicationCollectionInternal(
                context, userId);
        SmsApplicationData oldAppData = oldPackageName != null ?
@@ -642,8 +644,7 @@ public final class SmsApplication {
            AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
            if (oldPackageName != null) {
                try {
                    int uid = packageManager.getPackageInfoAsUser(
                            oldPackageName, 0, userId).applicationInfo.uid;
                    int uid = packageManager.getPackageInfo(oldPackageName, 0).applicationInfo.uid;
                    setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
                } catch (NameNotFoundException e) {
                    Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
@@ -807,9 +808,16 @@ public final class SmsApplication {
        }

        private void onPackageChanged() {
            PackageManager packageManager = mContext.getPackageManager();
            int userId;
            try {
                userId = getSendingUser().getIdentifier();
            } catch (NullPointerException e) {
                // This should never happen in prod -- unit tests will put the receiver into a
                // unusual state where the pending result is null, which produces a NPE when calling
                // getSendingUserId. Just pretend like it's the system user for testing.
                userId = UserHandle.USER_SYSTEM;
            }
            Context userContext = mContext;
            final int userId = getSendingUserId();
            if (userId != UserHandle.USER_SYSTEM) {
                try {
                    userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
@@ -820,10 +828,11 @@ public final class SmsApplication {
                    }
                }
            }
            PackageManager packageManager = userContext.getPackageManager();
            // Ensure this component is still configured as the preferred activity
            ComponentName componentName = getDefaultSendToApplication(userContext, true);
            if (componentName != null) {
                configurePreferredActivity(packageManager, componentName, userId);
                configurePreferredActivity(packageManager, componentName);
            }
        }
    }
@@ -835,41 +844,36 @@ public final class SmsApplication {

    @UnsupportedAppUsage
    private static void configurePreferredActivity(PackageManager packageManager,
            ComponentName componentName, int userId) {
            ComponentName componentName) {
        // Add the four activity preferences we want to direct to this app.
        replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMS);
        replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMSTO);
        replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMS);
        replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMSTO);
        replacePreferredActivity(packageManager, componentName, SCHEME_SMS);
        replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO);
        replacePreferredActivity(packageManager, componentName, SCHEME_MMS);
        replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);
    }

    /**
     * Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
     */
    private static void replacePreferredActivity(PackageManager packageManager,
            ComponentName componentName, int userId, String scheme) {
            ComponentName componentName, String scheme) {
        // Build the set of existing activities that handle this scheme
        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
        List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivitiesAsUser(
                intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER,
                userId);
        List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(
                intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);

        // Build the set of ComponentNames for these activities
        final int n = resolveInfoList.size();
        ComponentName[] set = new ComponentName[n];
        for (int i = 0; i < n; i++) {
            ResolveInfo info = resolveInfoList.get(i);
            set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
        }
        List<ComponentName> components = resolveInfoList.stream().map(info ->
                new ComponentName(info.activityInfo.packageName, info.activityInfo.name))
                .collect(Collectors.toList());

        // Update the preferred SENDTO activity for the specified scheme
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_SENDTO);
        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
        intentFilter.addDataScheme(scheme);
        packageManager.replacePreferredActivityAsUser(intentFilter,
        packageManager.replacePreferredActivity(intentFilter,
                IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
                set, componentName, userId);
                components, componentName);
    }

    /**
+2 −0
Original line number Diff line number Diff line
rule com.android.internal.telephony.SmsApplication* com.android.internal.telephony.tests.SmsApplication@1
rule android.telephony.PackageChangeReceiver* com.android.internal.telephony.tests.PackageChangeReceiver@1
rule com.android.internal.os.BackgroundThread* com.android.internal.telephony.tests.BackgroundThread@1
+55 −2
Original line number Diff line number Diff line
@@ -17,26 +17,34 @@
package com.android.internal.telephony.tests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.Manifest;
import android.app.AppOpsManager;
import android.app.role.RoleManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Telephony;
import android.telephony.TelephonyManager;
@@ -48,11 +56,15 @@ import com.android.internal.telephony.SmsApplication;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Unit tests for the {@link SmsApplication} utility class
@@ -80,6 +92,13 @@ public class SmsApplicationTest {
            AppOpsManager.OPSTR_READ_CELL_BROADCASTS
    };

    private static final Set<String> SCHEMES_FOR_PREFERRED_APP = Arrays.stream(new String[]{
            "mms",
            "mmsto",
            "sms",
            "smsto"
    }).collect(Collectors.toSet());

    @Mock private Context mContext;
    @Mock private TelephonyManager mTelephonyManager;
    @Mock private RoleManager mRoleManager;
@@ -94,13 +113,16 @@ public class SmsApplicationTest {
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
        when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
        when(mContext.createContextAsUser(isNotNull(), anyInt())).thenReturn(mContext);

        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
                .when(mPackageManager)
                .queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(), anyInt());
                .queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(),
                        nullable(UserHandle.class));
        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
                .when(mPackageManager)
                .queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(), anyInt());
                .queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(),
                        nullable(UserHandle.class));
        doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
                .when(mPackageManager)
                .queryIntentServicesAsUser(nullable(Intent.class), anyInt(),
@@ -137,6 +159,37 @@ public class SmsApplicationTest {
                AppOpsManager.MODE_ALLOWED);
    }

    @Test
    public void testPackageChanged() throws Exception {
        setupPackageInfosForCoreApps();
        SmsApplication.initSmsPackageMonitor(mContext);
        verify(mContext).createContextAsUser(eq(UserHandle.ALL), anyInt());
        ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
        verify(mContext).registerReceiver(captor.capture(), isNotNull(),
                isNull(), nullable(Handler.class));
        BroadcastReceiver smsPackageMonitor = captor.getValue();

        Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
        packageChangedIntent.setData(
                Uri.fromParts("package", TEST_COMPONENT_NAME.getPackageName(), null));
        smsPackageMonitor.onReceive(mContext, packageChangedIntent);

        ArgumentCaptor<IntentFilter> intentFilterCaptor =
                ArgumentCaptor.forClass(IntentFilter.class);
        verify(mPackageManager, times(SCHEMES_FOR_PREFERRED_APP.size()))
                .replacePreferredActivity(intentFilterCaptor.capture(),
                        eq(IntentFilter.MATCH_CATEGORY_SCHEME
                                | IntentFilter.MATCH_ADJUSTMENT_NORMAL),
                        isNotNull(List.class),
                        eq(new ComponentName(TEST_COMPONENT_NAME.getPackageName(), SEND_TO_NAME)));

        Set<String> capturedSchemes = intentFilterCaptor.getAllValues().stream()
                .map(intentFilter -> intentFilter.getDataScheme(0))
                .collect(Collectors.toSet());
        assertEquals(SCHEMES_FOR_PREFERRED_APP.size(), capturedSchemes.size());
        assertTrue(SCHEMES_FOR_PREFERRED_APP.containsAll(capturedSchemes));
    }

    private void setupPackageInfosForCoreApps() throws Exception {
        PackageInfo phonePackageInfo = new PackageInfo();
        ApplicationInfo phoneApplicationInfo = new ApplicationInfo();
+1 −1

File changed.

Contains only whitespace changes.