diff options
-rw-r--r-- | core/java/android/os/CarrierAssociatedAppEntry.aidl | 19 | ||||
-rw-r--r-- | core/java/android/os/CarrierAssociatedAppEntry.java | 68 | ||||
-rw-r--r-- | core/java/android/os/ISystemConfig.aidl | 5 | ||||
-rw-r--r-- | core/java/android/os/SystemConfigManager.java | 25 | ||||
-rwxr-xr-x | core/java/android/provider/Settings.java | 7 | ||||
-rw-r--r-- | core/java/com/android/server/SystemConfig.java | 29 | ||||
-rw-r--r-- | services/java/com/android/server/SystemConfigService.java | 16 | ||||
-rw-r--r-- | telephony/common/com/android/internal/telephony/CarrierAppUtils.java | 158 |
8 files changed, 263 insertions, 64 deletions
diff --git a/core/java/android/os/CarrierAssociatedAppEntry.aidl b/core/java/android/os/CarrierAssociatedAppEntry.aidl new file mode 100644 index 000000000000..a9b1055ee174 --- /dev/null +++ b/core/java/android/os/CarrierAssociatedAppEntry.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +parcelable CarrierAssociatedAppEntry; diff --git a/core/java/android/os/CarrierAssociatedAppEntry.java b/core/java/android/os/CarrierAssociatedAppEntry.java new file mode 100644 index 000000000000..13f6eb63e29c --- /dev/null +++ b/core/java/android/os/CarrierAssociatedAppEntry.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.os; + +/** + * Represents a carrier app entry for use with {@link SystemConfigService}. + * + * @hide + */ +public final class CarrierAssociatedAppEntry implements Parcelable { + + /** + * For carrier-associated app entries that don't specify the addedInSdk XML + * attribute. + */ + public static final int SDK_UNSPECIFIED = -1; + + public final String packageName; + /** May be {@link #SDK_UNSPECIFIED}. */ + public final int addedInSdk; + + public CarrierAssociatedAppEntry(String packageName, int addedInSdk) { + this.packageName = packageName; + this.addedInSdk = addedInSdk; + } + + public CarrierAssociatedAppEntry(Parcel in) { + packageName = in.readString(); + addedInSdk = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(packageName); + dest.writeInt(addedInSdk); + } + + public static final Parcelable.Creator<CarrierAssociatedAppEntry> CREATOR = + new Parcelable.Creator<CarrierAssociatedAppEntry>() { + @Override + public CarrierAssociatedAppEntry createFromParcel(Parcel source) { + return new CarrierAssociatedAppEntry(source); + } + + @Override + public CarrierAssociatedAppEntry[] newArray(int size) { + return new CarrierAssociatedAppEntry[size]; + } + }; +} diff --git a/core/java/android/os/ISystemConfig.aidl b/core/java/android/os/ISystemConfig.aidl index d3b029854112..52f0ce1f054f 100644 --- a/core/java/android/os/ISystemConfig.aidl +++ b/core/java/android/os/ISystemConfig.aidl @@ -30,4 +30,9 @@ interface ISystemConfig { * @see SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierAssociatedApps */ Map getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); + + /** + * @see SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries + */ + Map getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries(); } diff --git a/core/java/android/os/SystemConfigManager.java b/core/java/android/os/SystemConfigManager.java index 3a9ce2fa85f1..12a1ffaf69c1 100644 --- a/core/java/android/os/SystemConfigManager.java +++ b/core/java/android/os/SystemConfigManager.java @@ -88,4 +88,29 @@ public class SystemConfigManager { return Collections.emptyMap(); } } + + /** + * Returns a map that describes helper apps associated with carrier apps that, like the apps + * returned by {@link #getDisabledUntilUsedPreinstalledCarrierApps()}, should be disabled until + * the correct SIM is inserted into the device. + * + * <p>TODO(b/159069037) expose this and get rid of the other method that omits SDK version. + * + * @return A map with keys corresponding to package names returned by + * {@link #getDisabledUntilUsedPreinstalledCarrierApps()} and values as lists of package + * names of helper apps and the SDK versions when they were first added. + * + * @hide + */ + @RequiresPermission(Manifest.permission.READ_CARRIER_APP_INFO) + public @NonNull Map<String, List<CarrierAssociatedAppEntry>> + getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries() { + try { + return (Map<String, List<CarrierAssociatedAppEntry>>) + mInterface.getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries(); + } catch (RemoteException e) { + Log.e(TAG, "Caught remote exception", e); + return Collections.emptyMap(); + } + } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index fbe7bb9f5f40..3055c809a3b7 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -8521,14 +8521,15 @@ public final class Settings { public static final int VR_DISPLAY_MODE_OFF = 1; /** - * Whether CarrierAppUtils#disableCarrierAppsUntilPrivileged has been executed at least - * once. + * The latest SDK version that CarrierAppUtils#disableCarrierAppsUntilPrivileged has been + * executed for. * * <p>This is used to ensure that we only take one pass which will disable apps that are not * privileged (if any). From then on, we only want to enable apps (when a matching SIM is * inserted), to avoid disabling an app that the user might actively be using. * - * <p>Will be set to 1 once executed. + * <p>Will be set to {@link android.os.Build.VERSION#SDK_INT} once executed. Note that older + * SDK versions prior to R set 1 for this value. * * @hide */ diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index d9ca9c2f87f5..ea390cd71e31 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -24,6 +24,7 @@ import android.content.ComponentName; import android.content.pm.FeatureInfo; import android.content.pm.PackageManager; import android.os.Build; +import android.os.CarrierAssociatedAppEntry; import android.os.Environment; import android.os.FileUtils; import android.os.Process; @@ -198,8 +199,8 @@ public class SystemConfig { // These are the packages of carrier-associated apps which should be disabled until used until // a SIM is inserted which grants carrier privileges to that carrier app. - final ArrayMap<String, List<String>> mDisabledUntilUsedPreinstalledCarrierAssociatedApps = - new ArrayMap<>(); + final ArrayMap<String, List<CarrierAssociatedAppEntry>> + mDisabledUntilUsedPreinstalledCarrierAssociatedApps = new ArrayMap<>(); final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>(); final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>(); @@ -331,7 +332,8 @@ public class SystemConfig { return mDisabledUntilUsedPreinstalledCarrierApps; } - public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() { + public ArrayMap<String, List<CarrierAssociatedAppEntry>> + getDisabledUntilUsedPreinstalledCarrierAssociatedApps() { return mDisabledUntilUsedPreinstalledCarrierAssociatedApps; } @@ -954,7 +956,23 @@ public class SystemConfig { + "> without package or carrierAppPackage in " + permFile + " at " + parser.getPositionDescription()); } else { - List<String> associatedPkgs = + // APKs added to system images via OTA should specify the addedInSdk + // attribute, otherwise they may be enabled-by-default in too many + // cases. See CarrierAppUtils for more info. + int addedInSdk = CarrierAssociatedAppEntry.SDK_UNSPECIFIED; + String addedInSdkStr = parser.getAttributeValue(null, "addedInSdk"); + if (!TextUtils.isEmpty(addedInSdkStr)) { + try { + addedInSdk = Integer.parseInt(addedInSdkStr); + } catch (NumberFormatException e) { + Slog.w(TAG, "<" + name + "> addedInSdk not an integer in " + + permFile + " at " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + break; + } + } + List<CarrierAssociatedAppEntry> associatedPkgs = mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get( carrierPkgname); if (associatedPkgs == null) { @@ -962,7 +980,8 @@ public class SystemConfig { mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put( carrierPkgname, associatedPkgs); } - associatedPkgs.add(pkgname); + associatedPkgs.add( + new CarrierAssociatedAppEntry(pkgname, addedInSdk)); } } else { logNotAllowedInPartition(name, permFile, parser); diff --git a/services/java/com/android/server/SystemConfigService.java b/services/java/com/android/server/SystemConfigService.java index e8ab10124ef8..1801f3bca30e 100644 --- a/services/java/com/android/server/SystemConfigService.java +++ b/services/java/com/android/server/SystemConfigService.java @@ -15,6 +15,9 @@ */ package com.android.server; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; + import android.Manifest; import android.content.Context; import android.os.ISystemConfig; @@ -46,6 +49,19 @@ public class SystemConfigService extends SystemService { "getDisabledUntilUsedPreInstalledCarrierAssociatedApps requires" + " READ_CARRIER_APP_INFO"); return SystemConfig.getInstance() + .getDisabledUntilUsedPreinstalledCarrierAssociatedApps().entrySet().stream() + .collect(toMap( + Map.Entry::getKey, + e -> e.getValue().stream().map(app -> app.packageName) + .collect(toList()))); + } + + @Override + public Map getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries() { + mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO, + "getDisabledUntilUsedPreInstalledCarrierAssociatedAppEntries requires" + + " READ_CARRIER_APP_INFO"); + return SystemConfig.getInstance() .getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); } }; diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java index 4606fb4b631c..e57b03098758 100644 --- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java +++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java @@ -21,6 +21,8 @@ import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.os.Build; +import android.os.CarrierAssociatedAppEntry; import android.os.SystemConfigManager; import android.os.UserHandle; import android.permission.PermissionManager; @@ -79,8 +81,8 @@ public final class CarrierAppUtils { SystemConfigManager config = context.getSystemService(SystemConfigManager.class); Set<String> systemCarrierAppsDisabledUntilUsed = config.getDisabledUntilUsedPreinstalledCarrierApps(); - Map<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = - config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); + Map<String, List<CarrierAssociatedAppEntry>> systemCarrierAssociatedAppsDisabledUntilUsed = + config.getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries(); ContentResolver contentResolver = getContentResolverForUser(context, userId); disableCarrierAppsUntilPrivileged(callingPackage, telephonyManager, contentResolver, userId, systemCarrierAppsDisabledUntilUsed, @@ -107,8 +109,8 @@ public final class CarrierAppUtils { Set<String> systemCarrierAppsDisabledUntilUsed = config.getDisabledUntilUsedPreinstalledCarrierApps(); - Map<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed = - config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps(); + Map<String, List<CarrierAssociatedAppEntry>> systemCarrierAssociatedAppsDisabledUntilUsed = + config.getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries(); ContentResolver contentResolver = getContentResolverForUser(context, userId); disableCarrierAppsUntilPrivileged(callingPackage, null /* telephonyManager */, contentResolver, userId, systemCarrierAppsDisabledUntilUsed, @@ -138,8 +140,8 @@ public final class CarrierAppUtils { public static void disableCarrierAppsUntilPrivileged(String callingPackage, @Nullable TelephonyManager telephonyManager, ContentResolver contentResolver, int userId, Set<String> systemCarrierAppsDisabledUntilUsed, - Map<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed, - Context context) { + Map<String, List<CarrierAssociatedAppEntry>> + systemCarrierAssociatedAppsDisabledUntilUsed, Context context) { PackageManager packageManager = context.getPackageManager(); PermissionManager permissionManager = (PermissionManager) context.getSystemService(Context.PERMISSION_SERVICE); @@ -149,12 +151,17 @@ public final class CarrierAppUtils { return; } - Map<String, List<ApplicationInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper( + Map<String, List<AssociatedAppInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper( userId, systemCarrierAssociatedAppsDisabledUntilUsed, context); List<String> enabledCarrierPackages = new ArrayList<>(); - boolean hasRunOnce = Settings.Secure.getInt(contentResolver, - Settings.Secure.CARRIER_APPS_HANDLED, 0) == 1; + int carrierAppsHandledSdk = + Settings.Secure.getInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 0); + if (DEBUG) { + Log.i(TAG, "Last execution SDK: " + carrierAppsHandledSdk); + } + boolean hasRunEver = carrierAppsHandledSdk != 0; // SDKs < R used to just set 1 here + boolean hasRunForSdk = carrierAppsHandledSdk == Build.VERSION.SDK_INT; try { for (ApplicationInfo ai : candidates) { @@ -166,10 +173,10 @@ public final class CarrierAppUtils { // add hiddenUntilInstalled flag for carrier apps and associated apps packageManager.setSystemAppState( packageName, PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN); - List<ApplicationInfo> associatedAppList = associatedApps.get(packageName); + List<AssociatedAppInfo> associatedAppList = associatedApps.get(packageName); if (associatedAppList != null) { - for (ApplicationInfo associatedApp : associatedAppList) { - packageManager.setSystemAppState(associatedApp.packageName, + for (AssociatedAppInfo associatedApp : associatedAppList) { + packageManager.setSystemAppState(associatedApp.appInfo.packageName, PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN); } } @@ -184,7 +191,7 @@ public final class CarrierAppUtils { || enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) { - Log.i(TAG, "Update state(" + packageName + "): ENABLED for user " + Log.i(TAG, "Update state (" + packageName + "): ENABLED for user " + userId); context.createContextAsUser(UserHandle.of(userId), 0) .getPackageManager() @@ -200,28 +207,37 @@ public final class CarrierAppUtils { // Also enable any associated apps for this carrier app. if (associatedAppList != null) { - for (ApplicationInfo associatedApp : associatedAppList) { + for (AssociatedAppInfo associatedApp : associatedAppList) { int associatedAppEnabledSetting = context .createContextAsUser(UserHandle.of(userId), 0) .getPackageManager() - .getApplicationEnabledSetting(associatedApp.packageName); + .getApplicationEnabledSetting( + associatedApp.appInfo.packageName); + boolean associatedAppInstalled = (associatedApp.appInfo.flags + & ApplicationInfo.FLAG_INSTALLED) != 0; + if (DEBUG) { + Log.i(TAG, "(hasPrivileges) associated app " + + associatedApp.appInfo.packageName + ", enabled = " + + associatedAppEnabledSetting + ", installed = " + + associatedAppInstalled); + } if (associatedAppEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT || associatedAppEnabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED - || (associatedApp.flags - & ApplicationInfo.FLAG_INSTALLED) == 0) { - Log.i(TAG, "Update associated state(" + associatedApp.packageName - + "): ENABLED for user " + userId); + || !associatedAppInstalled) { + Log.i(TAG, "Update associated state (" + + associatedApp.appInfo.packageName + "): ENABLED for user " + + userId); context.createContextAsUser(UserHandle.of(userId), 0) .getPackageManager() - .setSystemAppState(associatedApp.packageName, + .setSystemAppState(associatedApp.appInfo.packageName, PackageManager.SYSTEM_APP_STATE_INSTALLED); context.createPackageContextAsUser( callingPackage, 0, UserHandle.of(userId)) .getPackageManager() .setApplicationEnabledSetting( - associatedApp.packageName, + associatedApp.appInfo.packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } @@ -236,7 +252,7 @@ public final class CarrierAppUtils { if (!isUpdatedSystemApp(ai) && enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) { - Log.i(TAG, "Update state(" + packageName + Log.i(TAG, "Update state (" + packageName + "): DISABLED_UNTIL_USED for user " + userId); context.createContextAsUser(UserHandle.of(userId), 0) .getPackageManager() @@ -244,37 +260,56 @@ public final class CarrierAppUtils { packageName, PackageManager.SYSTEM_APP_STATE_UNINSTALLED); } - // Also disable any associated apps for this carrier app if this is the first - // run. We avoid doing this a second time because it is brittle to rely on the - // distinction between "default" and "enabled". - if (!hasRunOnce) { - if (associatedAppList != null) { - for (ApplicationInfo associatedApp : associatedAppList) { - int associatedAppEnabledSetting = context - .createContextAsUser(UserHandle.of(userId), 0) + // Associated apps are more brittle, because we can't rely on the distinction + // between "default" and "enabled". To account for this, we have two cases: + // 1. We've never run before, so we're fine to disable all associated apps. + // 2. We've run before, but not on this SDK version, so we will only operate on + // apps with addedInSdk in the range (lastHandledSdk, currentSdk]. + // Otherwise, don't touch the associated apps. + if (associatedAppList != null) { + for (AssociatedAppInfo associatedApp : associatedAppList) { + boolean allowDisable = !hasRunEver || (!hasRunForSdk + && associatedApp.addedInSdk + != CarrierAssociatedAppEntry.SDK_UNSPECIFIED + && associatedApp.addedInSdk > carrierAppsHandledSdk + && associatedApp.addedInSdk <= Build.VERSION.SDK_INT); + int associatedAppEnabledSetting = context + .createContextAsUser(UserHandle.of(userId), 0) + .getPackageManager() + .getApplicationEnabledSetting( + associatedApp.appInfo.packageName); + boolean associatedAppInstalled = (associatedApp.appInfo.flags + & ApplicationInfo.FLAG_INSTALLED) != 0; + if (DEBUG) { + Log.i(TAG, "(!hasPrivileges) associated app " + + associatedApp.appInfo.packageName + ", allowDisable = " + + allowDisable + ", addedInSdk = " + + associatedApp.addedInSdk + ", enabled = " + + associatedAppEnabledSetting + ", installed = " + + associatedAppInstalled); + } + if (allowDisable + && associatedAppEnabledSetting + == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + && associatedAppInstalled) { + Log.i(TAG, + "Update associated state (" + + associatedApp.appInfo.packageName + + "): DISABLED_UNTIL_USED for user " + userId); + context.createContextAsUser(UserHandle.of(userId), 0) .getPackageManager() - .getApplicationEnabledSetting(associatedApp.packageName); - if (associatedAppEnabledSetting - == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT - && (associatedApp.flags - & ApplicationInfo.FLAG_INSTALLED) != 0) { - Log.i(TAG, - "Update associated state(" + associatedApp.packageName - + "): DISABLED_UNTIL_USED for user " + userId); - context.createContextAsUser(UserHandle.of(userId), 0) - .getPackageManager() - .setSystemAppState(associatedApp.packageName, - PackageManager.SYSTEM_APP_STATE_UNINSTALLED); - } + .setSystemAppState(associatedApp.appInfo.packageName, + PackageManager.SYSTEM_APP_STATE_UNINSTALLED); } } } } } - // Mark the execution so we do not disable apps again. - if (!hasRunOnce) { - Settings.Secure.putInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 1); + // Mark the execution so we do not disable apps again on this SDK version. + if (!hasRunEver || !hasRunForSdk) { + Settings.Secure.putInt(contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, + Build.VERSION.SDK_INT); } if (!enabledCarrierPackages.isEmpty()) { @@ -360,28 +395,28 @@ public final class CarrierAppUtils { return apps; } - private static Map<String, List<ApplicationInfo>> getDefaultCarrierAssociatedAppsHelper( - int userId, Map<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed, - Context context) { + private static Map<String, List<AssociatedAppInfo>> getDefaultCarrierAssociatedAppsHelper( + int userId, Map<String, List<CarrierAssociatedAppEntry>> + systemCarrierAssociatedAppsDisabledUntilUsed, Context context) { int size = systemCarrierAssociatedAppsDisabledUntilUsed.size(); - Map<String, List<ApplicationInfo>> associatedApps = new ArrayMap<>(size); - for (Map.Entry<String, List<String>> entry + Map<String, List<AssociatedAppInfo>> associatedApps = new ArrayMap<>(size); + for (Map.Entry<String, List<CarrierAssociatedAppEntry>> entry : systemCarrierAssociatedAppsDisabledUntilUsed.entrySet()) { String carrierAppPackage = entry.getKey(); - List<String> associatedAppPackages = entry.getValue(); + List<CarrierAssociatedAppEntry> associatedAppPackages = entry.getValue(); for (int j = 0; j < associatedAppPackages.size(); j++) { + CarrierAssociatedAppEntry associatedApp = associatedAppPackages.get(j); ApplicationInfo ai = - getApplicationInfoIfSystemApp( - userId, associatedAppPackages.get(j), context); + getApplicationInfoIfSystemApp(userId, associatedApp.packageName, context); // Only update enabled state for the app on /system. Once it has been updated we // shouldn't touch it. if (ai != null && !isUpdatedSystemApp(ai)) { - List<ApplicationInfo> appList = associatedApps.get(carrierAppPackage); + List<AssociatedAppInfo> appList = associatedApps.get(carrierAppPackage); if (appList == null) { appList = new ArrayList<>(); associatedApps.put(carrierAppPackage, appList); } - appList.add(ai); + appList.add(new AssociatedAppInfo(ai, associatedApp.addedInSdk)); } } } @@ -406,4 +441,15 @@ public final class CarrierAppUtils { } return null; } + + private static final class AssociatedAppInfo { + public final ApplicationInfo appInfo; + // Might be CarrierAssociatedAppEntry.SDK_UNSPECIFIED. + public final int addedInSdk; + + AssociatedAppInfo(ApplicationInfo appInfo, int addedInSdk) { + this.appInfo = appInfo; + this.addedInSdk = addedInSdk; + } + } } |