Merge "Add support for carrier "associated" apps." into nyc-mr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
94ae1e739f
@@ -6229,6 +6229,20 @@ public final class Settings {
|
||||
*/
|
||||
public static final int VR_DISPLAY_MODE_OFF = 1;
|
||||
|
||||
/**
|
||||
* Whether CarrierAppUtils#disableCarrierAppsUntilPrivileged has been executed at least
|
||||
* once.
|
||||
*
|
||||
* <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.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String CARRIER_APPS_HANDLED = "carrier_apps_handled";
|
||||
|
||||
/**
|
||||
* Whether parent user can access remote contact in managed profile.
|
||||
*
|
||||
|
||||
@@ -42,6 +42,8 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Loads global system configuration info.
|
||||
@@ -122,6 +124,11 @@ public class SystemConfig {
|
||||
// These are the permitted backup transport service components
|
||||
final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
|
||||
|
||||
// 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<>();
|
||||
|
||||
public static SystemConfig getInstance() {
|
||||
synchronized (SystemConfig.class) {
|
||||
if (sInstance == null) {
|
||||
@@ -183,6 +190,10 @@ public class SystemConfig {
|
||||
return mBackupTransportWhitelist;
|
||||
}
|
||||
|
||||
public ArrayMap<String, List<String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps() {
|
||||
return mDisabledUntilUsedPreinstalledCarrierAssociatedApps;
|
||||
}
|
||||
|
||||
SystemConfig() {
|
||||
// Read configuration from system
|
||||
readPermissions(Environment.buildPath(
|
||||
@@ -476,6 +487,26 @@ public class SystemConfig {
|
||||
}
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
} else if ("disabled-until-used-preinstalled-carrier-associated-app".equals(name)
|
||||
&& allowAppConfigs) {
|
||||
String pkgname = parser.getAttributeValue(null, "package");
|
||||
String carrierPkgname = parser.getAttributeValue(null, "carrierAppPackage");
|
||||
if (pkgname == null || carrierPkgname == null) {
|
||||
Slog.w(TAG, "<disabled-until-used-preinstalled-carrier-associated-app"
|
||||
+ " without package or carrierAppPackage in " + permFile + " at "
|
||||
+ parser.getPositionDescription());
|
||||
} else {
|
||||
List<String> associatedPkgs =
|
||||
mDisabledUntilUsedPreinstalledCarrierAssociatedApps.get(
|
||||
carrierPkgname);
|
||||
if (associatedPkgs == null) {
|
||||
associatedPkgs = new ArrayList<>();
|
||||
mDisabledUntilUsedPreinstalledCarrierAssociatedApps.put(
|
||||
carrierPkgname, associatedPkgs);
|
||||
}
|
||||
associatedPkgs.add(pkgname);
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
} else {
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
continue;
|
||||
|
||||
@@ -1963,10 +1963,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
PackageManagerService m = new PackageManagerService(context, installer,
|
||||
factoryTest, onlyCore);
|
||||
m.enableSystemUserPackages();
|
||||
// Disable any carrier apps. We do this very early in boot to prevent the apps from being
|
||||
// disabled after already being started.
|
||||
CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
|
||||
UserHandle.USER_SYSTEM);
|
||||
ServiceManager.addService("package", m);
|
||||
return m;
|
||||
}
|
||||
@@ -17875,6 +17871,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
|
||||
public void systemReady() {
|
||||
mSystemReady = true;
|
||||
|
||||
// Disable any carrier apps. We do this very early in boot to prevent the apps from being
|
||||
// disabled after already being started.
|
||||
CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this,
|
||||
mContext.getContentResolver(), UserHandle.USER_SYSTEM);
|
||||
|
||||
// Read the compatibilty setting when the system is ready.
|
||||
boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
|
||||
mContext.getContentResolver(),
|
||||
|
||||
@@ -17,18 +17,23 @@
|
||||
package com.android.internal.telephony;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.SystemConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Utilities for handling carrier applications.
|
||||
@@ -53,6 +58,11 @@ public final class CarrierAppUtils {
|
||||
* in the default state (e.g. not explicitly DISABLED/DISABLED_BY_USER/ENABLED), or we enable if
|
||||
* the app is carrier privileged and in either the default state or DISABLED_UNTIL_USED.
|
||||
*
|
||||
* In addition, there is a list of carrier-associated applications in
|
||||
* {@link SystemConfig#getDisabledUntilUsedPreinstalledCarrierAssociatedApps}. Each app in this
|
||||
* list is associated with a carrier app. When the given carrier app is enabled/disabled per the
|
||||
* above, the associated applications are enabled/disabled to match.
|
||||
*
|
||||
* When enabling a carrier app we also grant it default permissions.
|
||||
*
|
||||
* This method is idempotent and is safe to be called at any time; it should be called once at
|
||||
@@ -60,19 +70,24 @@ public final class CarrierAppUtils {
|
||||
* privileged apps may have changed.
|
||||
*/
|
||||
public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
|
||||
IPackageManager packageManager, TelephonyManager telephonyManager, int userId) {
|
||||
IPackageManager packageManager, TelephonyManager telephonyManager,
|
||||
ContentResolver contentResolver, int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
|
||||
}
|
||||
SystemConfig config = SystemConfig.getInstance();
|
||||
String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
|
||||
com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
|
||||
disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager, userId,
|
||||
systemCarrierAppsDisabledUntilUsed);
|
||||
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
|
||||
config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
|
||||
disableCarrierAppsUntilPrivileged(callingPackage, packageManager, telephonyManager,
|
||||
contentResolver, userId, systemCarrierAppsDisabledUntilUsed,
|
||||
systemCarrierAssociatedAppsDisabledUntilUsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #disableCarrierAppsUntilPrivileged(String, IPackageManager, TelephonyManager,
|
||||
* int)}, but assumes that no carrier apps have carrier privileges.
|
||||
* ContentResolver, int)}, but assumes that no carrier apps have carrier privileges.
|
||||
*
|
||||
* This prevents a potential race condition on first boot - since the app's default state is
|
||||
* enabled, we will initially disable it when the telephony stack is first initialized as it has
|
||||
@@ -82,29 +97,43 @@ public final class CarrierAppUtils {
|
||||
* Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
|
||||
*/
|
||||
public synchronized static void disableCarrierAppsUntilPrivileged(String callingPackage,
|
||||
IPackageManager packageManager, int userId) {
|
||||
IPackageManager packageManager, ContentResolver contentResolver, int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "disableCarrierAppsUntilPrivileged");
|
||||
}
|
||||
SystemConfig config = SystemConfig.getInstance();
|
||||
String[] systemCarrierAppsDisabledUntilUsed = Resources.getSystem().getStringArray(
|
||||
com.android.internal.R.array.config_disabledUntilUsedPreinstalledCarrierApps);
|
||||
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
|
||||
config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
|
||||
disableCarrierAppsUntilPrivileged(callingPackage, packageManager,
|
||||
null /* telephonyManager */, userId, systemCarrierAppsDisabledUntilUsed);
|
||||
null /* telephonyManager */, contentResolver, userId,
|
||||
systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed);
|
||||
}
|
||||
|
||||
// Must be public b/c framework unit tests can't access package-private methods.
|
||||
@VisibleForTesting
|
||||
public static void disableCarrierAppsUntilPrivileged(String callingPackage,
|
||||
IPackageManager packageManager, @Nullable TelephonyManager telephonyManager, int userId,
|
||||
String[] systemCarrierAppsDisabledUntilUsed) {
|
||||
IPackageManager packageManager, @Nullable TelephonyManager telephonyManager,
|
||||
ContentResolver contentResolver, int userId,
|
||||
String[] systemCarrierAppsDisabledUntilUsed,
|
||||
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) {
|
||||
List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper(packageManager,
|
||||
userId, systemCarrierAppsDisabledUntilUsed);
|
||||
if (candidates == null || candidates.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, List<ApplicationInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper(
|
||||
packageManager,
|
||||
userId,
|
||||
systemCarrierAssociatedAppsDisabledUntilUsed);
|
||||
|
||||
List<String> enabledCarrierPackages = new ArrayList<>();
|
||||
|
||||
boolean hasRunOnce = Settings.Secure.getIntForUser(
|
||||
contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 0, userId) == 1;
|
||||
|
||||
try {
|
||||
for (ApplicationInfo ai : candidates) {
|
||||
String packageName = ai.packageName;
|
||||
@@ -112,33 +141,92 @@ public final class CarrierAppUtils {
|
||||
telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
|
||||
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
|
||||
|
||||
// Only update enabled state for the app on /system. Once it has been updated we
|
||||
// shouldn't touch it.
|
||||
if (!ai.isUpdatedSystemApp()) {
|
||||
if (hasPrivileges
|
||||
&& (ai.enabledSetting == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|
||||
if (hasPrivileges) {
|
||||
// Only update enabled state for the app on /system. Once it has been
|
||||
// updated we shouldn't touch it.
|
||||
if (!ai.isUpdatedSystemApp()
|
||||
&& (ai.enabledSetting ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|
||||
|| ai.enabledSetting ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
|
||||
Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
|
||||
+ userId);
|
||||
packageManager.setApplicationEnabledSetting(packageName,
|
||||
packageManager.setApplicationEnabledSetting(
|
||||
packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP, userId, callingPackage);
|
||||
} else if (!hasPrivileges
|
||||
PackageManager.DONT_KILL_APP,
|
||||
userId,
|
||||
callingPackage);
|
||||
}
|
||||
|
||||
// Also enable any associated apps for this carrier app.
|
||||
List<ApplicationInfo> associatedAppList = associatedApps.get(packageName);
|
||||
if (associatedAppList != null) {
|
||||
for (ApplicationInfo associatedApp : associatedAppList) {
|
||||
if (associatedApp.enabledSetting ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|
||||
|| associatedApp.enabledSetting ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
|
||||
Slog.i(TAG, "Update associated state(" + associatedApp.packageName
|
||||
+ "): ENABLED for user " + userId);
|
||||
packageManager.setApplicationEnabledSetting(
|
||||
associatedApp.packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||
PackageManager.DONT_KILL_APP,
|
||||
userId,
|
||||
callingPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always re-grant default permissions to carrier apps w/ privileges.
|
||||
enabledCarrierPackages.add(ai.packageName);
|
||||
} else { // No carrier privileges
|
||||
// Only update enabled state for the app on /system. Once it has been
|
||||
// updated we shouldn't touch it.
|
||||
if (!ai.isUpdatedSystemApp()
|
||||
&& ai.enabledSetting ==
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
|
||||
Slog.i(TAG, "Update state(" + packageName
|
||||
+ "): DISABLED_UNTIL_USED for user " + userId);
|
||||
packageManager.setApplicationEnabledSetting(packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED, 0,
|
||||
userId, callingPackage);
|
||||
packageManager.setApplicationEnabledSetting(
|
||||
packageName,
|
||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
|
||||
0,
|
||||
userId,
|
||||
callingPackage);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
List<ApplicationInfo> associatedAppList = associatedApps.get(packageName);
|
||||
if (associatedAppList != null) {
|
||||
for (ApplicationInfo associatedApp : associatedAppList) {
|
||||
if (associatedApp.enabledSetting
|
||||
== PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
|
||||
Slog.i(TAG,
|
||||
"Update associated state(" + associatedApp.packageName
|
||||
+ "): DISABLED_UNTIL_USED for user " + userId);
|
||||
packageManager.setApplicationEnabledSetting(
|
||||
associatedApp.packageName,
|
||||
PackageManager
|
||||
.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
|
||||
0,
|
||||
userId,
|
||||
callingPackage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always re-grant default permissions to carrier apps w/ privileges.
|
||||
if (hasPrivileges) {
|
||||
enabledCarrierPackages.add(ai.packageName);
|
||||
}
|
||||
// Mark the execution so we do not disable apps again.
|
||||
if (!hasRunOnce) {
|
||||
Settings.Secure.putIntForUser(
|
||||
contentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 1, userId);
|
||||
}
|
||||
|
||||
if (!enabledCarrierPackages.isEmpty()) {
|
||||
@@ -190,8 +278,8 @@ public final class CarrierAppUtils {
|
||||
*
|
||||
* These are the apps subject to the hiding/showing logic in
|
||||
* {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager,
|
||||
* TelephonyManager, int)}, as well as the apps which should have default permissions granted,
|
||||
* when a matching SIM is inserted.
|
||||
* TelephonyManager, ContentResolver, int)}, as well as the apps which should have default
|
||||
* permissions granted, when a matching SIM is inserted.
|
||||
*
|
||||
* Whether or not the app is actually considered a default app depends on whether the app has
|
||||
* carrier privileges as determined by the SIMs in the device.
|
||||
@@ -205,30 +293,68 @@ public final class CarrierAppUtils {
|
||||
}
|
||||
|
||||
private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper(
|
||||
IPackageManager packageManager, int userId,
|
||||
IPackageManager packageManager,
|
||||
int userId,
|
||||
String[] systemCarrierAppsDisabledUntilUsed) {
|
||||
if (systemCarrierAppsDisabledUntilUsed == null
|
||||
|| systemCarrierAppsDisabledUntilUsed.length == 0) {
|
||||
return null;
|
||||
}
|
||||
List<ApplicationInfo> apps = null;
|
||||
try {
|
||||
apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.length);
|
||||
for (String packageName : systemCarrierAppsDisabledUntilUsed) {
|
||||
ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
|
||||
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId);
|
||||
if (ai == null) {
|
||||
// No app found for packageName
|
||||
continue;
|
||||
}
|
||||
if (!ai.isSystemApp()) {
|
||||
continue;
|
||||
}
|
||||
List<ApplicationInfo> apps = new ArrayList<>(systemCarrierAppsDisabledUntilUsed.length);
|
||||
for (int i = 0; i < systemCarrierAppsDisabledUntilUsed.length; i++) {
|
||||
String packageName = systemCarrierAppsDisabledUntilUsed[i];
|
||||
ApplicationInfo ai =
|
||||
getApplicationInfoIfSystemApp(packageManager, userId, packageName);
|
||||
if (ai != null) {
|
||||
apps.add(ai);
|
||||
}
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
|
||||
private static Map<String, List<ApplicationInfo>> getDefaultCarrierAssociatedAppsHelper(
|
||||
IPackageManager packageManager,
|
||||
int userId,
|
||||
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) {
|
||||
int size = systemCarrierAssociatedAppsDisabledUntilUsed.size();
|
||||
Map<String, List<ApplicationInfo>> associatedApps = new ArrayMap<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
String carrierAppPackage = systemCarrierAssociatedAppsDisabledUntilUsed.keyAt(i);
|
||||
List<String> associatedAppPackages =
|
||||
systemCarrierAssociatedAppsDisabledUntilUsed.valueAt(i);
|
||||
for (int j = 0; j < associatedAppPackages.size(); j++) {
|
||||
ApplicationInfo ai =
|
||||
getApplicationInfoIfSystemApp(
|
||||
packageManager, userId, associatedAppPackages.get(j));
|
||||
// Only update enabled state for the app on /system. Once it has been updated we
|
||||
// shouldn't touch it.
|
||||
if (ai != null && !ai.isUpdatedSystemApp()) {
|
||||
List<ApplicationInfo> appList = associatedApps.get(carrierAppPackage);
|
||||
if (appList == null) {
|
||||
appList = new ArrayList<>();
|
||||
associatedApps.put(carrierAppPackage, appList);
|
||||
}
|
||||
appList.add(ai);
|
||||
}
|
||||
}
|
||||
}
|
||||
return associatedApps;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ApplicationInfo getApplicationInfoIfSystemApp(
|
||||
IPackageManager packageManager,
|
||||
int userId,
|
||||
String packageName) {
|
||||
try {
|
||||
ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
|
||||
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, userId);
|
||||
if (ai != null && ai.isSystemApp()) {
|
||||
return ai;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "Could not reach PackageManager", e);
|
||||
}
|
||||
return apps;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user