Merge changes from topic "bugreport-stub" into rvc-dev

* changes:
  Reevaluate some carrier-associated apps' status on SDK changes.
  Add new "addedInSdk" attribute to carrier-associated apps.
This commit is contained in:
Hunter Knepshield
2020-06-18 17:01:01 +00:00
committed by Android (Google) Code Review
8 changed files with 263 additions and 64 deletions

View File

@@ -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;

View File

@@ -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];
}
};
}

View File

@@ -30,4 +30,9 @@ interface ISystemConfig {
* @see SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierAssociatedApps
*/
Map getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
/**
* @see SystemConfigManager#getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries
*/
Map getDisabledUntilUsedPreinstalledCarrierAssociatedAppEntries();
}

View File

@@ -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();
}
}
}

View File

@@ -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
*/

View File

@@ -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);

View File

@@ -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;
@@ -45,6 +48,19 @@ public class SystemConfigService extends SystemService {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_CARRIER_APP_INFO,
"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();
}

View File

@@ -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;
}
}
}