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

Commit fa4ac334 authored by Jeff Davidson's avatar Jeff Davidson
Browse files

Suppress SIM app dialog for locked devices and with bundled apps.

The platform supports a mechanism to bundle carrier apps but keep them
fully uninstalled until a matching SIM is inserted (see
CarrierAppUtils). However, the installation of such apps races against
the SIM app dialog which prompts the user to install that app, even as
it's being actively installed from the bundled APK.

To avoid this race, the SIM app dialog should treat
hidden-until-installed components the same way as it treats installed
components and avoid showing a prompt. The assumption is that if the
OEM configured an app in this state, then some external process should
be responsible for enabling it, and we don't need to prompt the user
about it.

Furthermore, if the user has yet to unlock credential-encrypted
storage, we cannot prompt them to install an app as the app store is
unlikely to be direct-boot-aware. We treat this case similarly to when
Setup Wizard hasn't run yet - wait for the user to unlock the device,
and then show a notification instead of a full-screen activity.

Bug: 134067502
Bug: 134067994
Test: Validated both scenarios on device
Change-Id: Ifd2df776982df6d83b316990c97d90b6c980d43d
parent df132566
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ public class ShowInstallAppNotificationReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        String pkgName = intent.getStringExtra(EXTRA_PACKAGE_NAME);

        if (!UiccProfile.isPackageInstalled(context, pkgName)) {
        if (!UiccProfile.isPackageBundled(context, pkgName)) {
            InstallCarrierAppUtils.showNotification(context, pkgName);
            InstallCarrierAppUtils.registerPackageInstallReceiver(context);
        }
+54 −21
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.os.Message;
import android.os.PersistableBundle;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.UserManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
@@ -141,14 +142,19 @@ public class UiccProfile extends IccCard {
                @Override
                public void onChange(boolean selfChange) {
                    mContext.getContentResolver().unregisterContentObserver(this);
                    for (String pkgName : getUninstalledCarrierPackages()) {
                        InstallCarrierAppUtils.showNotification(mContext, pkgName);
                        InstallCarrierAppUtils.registerPackageInstallReceiver(mContext);
                    showCarrierAppNotificationsIfPossible();
                }
            };

    private final BroadcastReceiver mUserUnlockReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            mContext.unregisterReceiver(this);
            showCarrierAppNotificationsIfPossible();
        }
    };

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mCarrierConfigChangedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
@@ -253,7 +259,7 @@ public class UiccProfile extends IccCard {

        IntentFilter intentfilter = new IntentFilter();
        intentfilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        c.registerReceiver(mReceiver, intentfilter);
        c.registerReceiver(mCarrierConfigChangedReceiver, intentfilter);
    }

    /**
@@ -275,7 +281,7 @@ public class UiccProfile extends IccCard {
            InstallCarrierAppUtils.unregisterPackageInstallReceiver(mContext);

            mCi.unregisterForOffOrNotAvailable(mHandler);
            mContext.unregisterReceiver(mReceiver);
            mContext.unregisterReceiver(mCarrierConfigChangedReceiver);

            if (mCatService != null) mCatService.dispose();
            for (UiccCardApplication app : mUiccApplications) {
@@ -1158,10 +1164,13 @@ public class UiccProfile extends IccCard {
        }
    }

    static boolean isPackageInstalled(Context context, String pkgName) {
    static boolean isPackageBundled(Context context, String pkgName) {
        PackageManager pm = context.getPackageManager();
        try {
            pm.getPackageInfo(pkgName, PackageManager.GET_ACTIVITIES);
            // We also match hidden-until-installed apps. The assumption here is that some other
            // mechanism (like CarrierAppUtils) would automatically enable such an app, so we
            // shouldn't prompt the user about it.
            pm.getApplicationInfo(pkgName, PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS);
            if (DBG) log(pkgName + " is installed.");
            return true;
        } catch (PackageManager.NameNotFoundException e) {
@@ -1188,22 +1197,46 @@ public class UiccProfile extends IccCard {

        synchronized (mLock) {
            mCarrierPrivilegeRegistrants.notifyRegistrants();
            boolean isProvisioned = Settings.Global.getInt(
                    mContext.getContentResolver(),
                    Settings.Global.DEVICE_PROVISIONED, 1) == 1;
            // Only show dialog if the phone is through with Setup Wizard.  Otherwise, wait for
            // completion and show a notification instead
            if (isProvisioned) {
            boolean isProvisioned = isProvisioned();
            boolean isUnlocked = isUserUnlocked();
            // Only show dialog if the phone is through with Setup Wizard and is unlocked.
            // Otherwise, wait for completion and unlock and show a notification instead.
            if (isProvisioned && isUnlocked) {
                for (String pkgName : getUninstalledCarrierPackages()) {
                    promptInstallCarrierApp(pkgName);
                }
            } else {
                if (!isProvisioned) {
                    final Uri uri = Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED);
                    mContext.getContentResolver().registerContentObserver(
                            uri,
                            false,
                            mProvisionCompleteContentObserver);
                }
                if (!isUnlocked) {
                    mContext.registerReceiver(
                            mUserUnlockReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
                }
            }
        }
    }

    private boolean isProvisioned() {
        return Settings.Global.getInt(
                mContext.getContentResolver(),
                Settings.Global.DEVICE_PROVISIONED, 1) == 1;
    }

    private boolean isUserUnlocked() {
        return mContext.getSystemService(UserManager.class).isUserUnlocked();
    }

    private void showCarrierAppNotificationsIfPossible() {
        if (isProvisioned() && isUserUnlocked()) {
            for (String pkgName : getUninstalledCarrierPackages()) {
                InstallCarrierAppUtils.showNotification(mContext, pkgName);
                InstallCarrierAppUtils.registerPackageInstallReceiver(mContext);
            }
        }
    }

@@ -1226,7 +1259,7 @@ public class UiccProfile extends IccCard {
        for (UiccAccessRule accessRule : accessRules) {
            String certHexString = accessRule.getCertificateHexString().toUpperCase();
            String pkgName = certPackageMap.get(certHexString);
            if (!TextUtils.isEmpty(pkgName) && !isPackageInstalled(mContext, pkgName)) {
            if (!TextUtils.isEmpty(pkgName) && !isPackageBundled(mContext, pkgName)) {
                uninstalledCarrierPackages.add(pkgName);
            }
        }
+2 −0
Original line number Diff line number Diff line
@@ -265,6 +265,8 @@ public class ContextFixture implements TestFixture<Context> {
                return Context.APP_OPS_SERVICE;
            } else if (serviceClass == TelecomManager.class) {
                return Context.TELECOM_SERVICE;
            } else if (serviceClass == UserManager.class) {
                return Context.USER_SERVICE;
            }
            return super.getSystemServiceName(serviceClass);
        }