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

Commit bbc757e0 authored by changbetty's avatar changbetty
Browse files

[Mainline] Copy the findBestComponent method from EuiccConnector to Settings

Make a copy of EuiccConnector#findBestComponent() into local method findEuiccService().

Bug: 147275124
Test: make RunSettingsRoboTests ROBOTEST_FILTER=ApplicationFeatureProviderImplTest
Change-Id: Ie81569d940fc354053469570e1506b1954d9f24d
parent 69a7e054
Loading
Loading
Loading
Loading
+98 −2
Original line number Diff line number Diff line
@@ -16,24 +16,30 @@

package com.android.settings.applications;

import android.Manifest;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.location.LocationManager;
import android.os.RemoteException;
import android.os.UserManager;
import android.service.euicc.EuiccService;
import android.telecom.DefaultDialerManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;

import androidx.annotation.VisibleForTesting;

import com.android.internal.telephony.SmsApplication;
import com.android.internal.telephony.euicc.EuiccConnector;
import com.android.settings.R;

import java.util.ArrayList;
@@ -41,12 +47,17 @@ import java.util.List;
import java.util.Set;

public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
    private static final String TAG = "AppFeatureProviderImpl";

    protected final Context mContext;
    private final PackageManager mPm;
    private final IPackageManager mPms;
    private final DevicePolicyManager mDpm;
    private final UserManager mUm;
    /** Flags to use when querying PackageManager for Euicc component implementations. */
    private static final int EUICC_QUERY_FLAGS =
            PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
                | PackageManager.GET_RESOLVED_FILTER;

    public ApplicationFeatureProviderImpl(Context context, PackageManager pm,
            IPackageManager pms, DevicePolicyManager dpm) {
@@ -143,7 +154,7 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
        }

        // Keep Euicc Service enabled.
        final ComponentInfo euicc = EuiccConnector.findBestComponent(mPm);
        final ComponentInfo euicc = findEuiccService(mPm);
        if (euicc != null) {
            keepEnabledPackages.add(euicc.packageName);
        }
@@ -239,4 +250,89 @@ public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvide
            mCallback.onListOfAppsResult(list);
        }
    }

    /**
     * Return the component info of the EuiccService to bind to, or null if none were found.
     */
    @VisibleForTesting
    ComponentInfo findEuiccService(PackageManager packageManager) {
        final Intent intent = new Intent(EuiccService.EUICC_SERVICE_INTERFACE);
        final List<ResolveInfo> resolveInfoList =
                packageManager.queryIntentServices(intent, EUICC_QUERY_FLAGS);
        final ComponentInfo bestComponent = findEuiccService(packageManager, resolveInfoList);
        if (bestComponent == null) {
            Log.w(TAG, "No valid EuiccService implementation found");
        }
        return bestComponent;
    }

    private ComponentInfo findEuiccService(
            PackageManager packageManager, List<ResolveInfo> resolveInfoList) {
        int bestPriority = Integer.MIN_VALUE;
        ComponentInfo bestComponent = null;
        if (resolveInfoList != null) {
            for (ResolveInfo resolveInfo : resolveInfoList) {
                if (!isValidEuiccComponent(packageManager, resolveInfo)) {
                    continue;
                }

                if (resolveInfo.filter.getPriority() > bestPriority) {
                    bestPriority = resolveInfo.filter.getPriority();
                    bestComponent = getComponentInfo(resolveInfo);
                }
            }
        }

        return bestComponent;
    }

    private boolean isValidEuiccComponent(
            PackageManager packageManager, ResolveInfo resolveInfo) {
        final ComponentInfo componentInfo = getComponentInfo(resolveInfo);
        final String packageName = componentInfo.packageName;

        // Verify that the app is privileged (via granting of a privileged permission).
        if (packageManager.checkPermission(
                Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS, packageName)
                != PackageManager.PERMISSION_GRANTED) {
            Log.e(TAG, "Package " + packageName
                    + " does not declare WRITE_EMBEDDED_SUBSCRIPTIONS");
            return false;
        }

        // Verify that only the system can access the component.
        final String permission;
        if (componentInfo instanceof ServiceInfo) {
            permission = ((ServiceInfo) componentInfo).permission;
        } else if (componentInfo instanceof ActivityInfo) {
            permission = ((ActivityInfo) componentInfo).permission;
        } else {
            throw new IllegalArgumentException("Can only verify services/activities");
        }
        if (!TextUtils.equals(permission, Manifest.permission.BIND_EUICC_SERVICE)) {
            Log.e(TAG, "Package " + packageName
                    + " does not require the BIND_EUICC_SERVICE permission");
            return false;
        }

        // Verify that the component declares a priority.
        if (resolveInfo.filter == null || resolveInfo.filter.getPriority() == 0) {
            Log.e(TAG, "Package " + packageName + " does not specify a priority");
            return false;
        }
        return true;
    }

    private ComponentInfo getComponentInfo(ResolveInfo resolveInfo) {
        if (resolveInfo.activityInfo != null) {
            return resolveInfo.activityInfo;
        }
        if (resolveInfo.serviceInfo != null) {
            return resolveInfo.serviceInfo;
        }
        if (resolveInfo.providerInfo != null) {
            return resolveInfo.providerInfo;
        }
        throw new IllegalStateException("Missing ComponentInfo!");
    }
}
+7 −33
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.applications;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

@@ -37,12 +38,10 @@ import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;

import com.android.internal.telephony.euicc.EuiccConnector;
import com.android.settings.testutils.ApplicationTestUtils;
import com.android.settingslib.testutils.shadow.ShadowDefaultDialerManager;
import com.android.settingslib.testutils.shadow.ShadowSmsApplication;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -51,8 +50,6 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;

@@ -109,12 +106,6 @@ public final class ApplicationFeatureProviderImplTest {
                mPackageManagerService, mDevicePolicyManager);
    }

    @After
    @Config(shadows = {ShadowEuiccConnector.class})
    public void tearDown() {
        ShadowEuiccConnector.reset();
    }

    private void verifyCalculateNumberOfPolicyInstalledApps(boolean async) {
        setUpUsersAndInstalledApps();

@@ -293,8 +284,7 @@ public final class ApplicationFeatureProviderImplTest {
    }

    @Test
    @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class,
            ShadowEuiccConnector.class})
    @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class})
    public void getKeepEnabledPackages_hasEuiccComponent_shouldContainEuiccPackage() {
        final String testDialer = "com.android.test.defaultdialer";
        final String testSms = "com.android.test.defaultsms";
@@ -305,7 +295,10 @@ public final class ApplicationFeatureProviderImplTest {
        ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
        final ComponentInfo componentInfo = new ComponentInfo();
        componentInfo.packageName = testEuicc;
        ShadowEuiccConnector.setBestComponent(componentInfo);

        ApplicationFeatureProviderImpl spyProvider = spy(new ApplicationFeatureProviderImpl(
                mContext, mPackageManager, mPackageManagerService, mDevicePolicyManager));
        doReturn(componentInfo).when(spyProvider).findEuiccService(mPackageManager);

        // Spy the real context to mock LocationManager.
        Context spyContext = spy(RuntimeEnvironment.application);
@@ -314,7 +307,7 @@ public final class ApplicationFeatureProviderImplTest {

        ReflectionHelpers.setField(mProvider, "mContext", spyContext);

        final Set<String> keepEnabledPackages = mProvider.getKeepEnabledPackages();
        final Set<String> keepEnabledPackages = spyProvider.getKeepEnabledPackages();

        assertThat(keepEnabledPackages).contains(testEuicc);
    }
@@ -391,23 +384,4 @@ public final class ApplicationFeatureProviderImplTest {
        resolveInfo.activityInfo = activityInfo;
        return resolveInfo;
    }

    @Implements(EuiccConnector.class)
    public static class ShadowEuiccConnector {

        private static ComponentInfo sBestComponent;

        @Implementation
        protected static ComponentInfo findBestComponent(PackageManager packageManager) {
            return sBestComponent;
        }

        public static void setBestComponent(ComponentInfo componentInfo) {
            sBestComponent = componentInfo;
        }

        public static void reset() {
            sBestComponent = null;
        }
    }
}