Merge "Create whitelisted apps for all users." into qt-dev
diff --git a/car-lib/src/android/car/content/pm/AppBlockingPackageInfo.java b/car-lib/src/android/car/content/pm/AppBlockingPackageInfo.java
index 3c1a356..02610ab 100644
--- a/car-lib/src/android/car/content/pm/AppBlockingPackageInfo.java
+++ b/car-lib/src/android/car/content/pm/AppBlockingPackageInfo.java
@@ -45,7 +45,7 @@
@IntDef(flag = true,
value = {FLAG_SYSTEM_APP, FLAG_WHOLE_ACTIVITY})
@Retention(RetentionPolicy.SOURCE)
- public @interface ConstrcutorFlags {}
+ public @interface ConstructorFlags {}
/**
* flags to give additional information on the package.
@@ -82,7 +82,7 @@
public AppBlockingPackageInfo(String packageName, int minRevisionCode, int maxRevisionCode,
- @ConstrcutorFlags int flags, @Nullable Signature[] signatures,
+ @ConstructorFlags int flags, @Nullable Signature[] signatures,
@Nullable String[] activities) {
if (packageName == null) {
throw new IllegalArgumentException("packageName cannot be null");
@@ -156,8 +156,6 @@
return false;
}
-
-
@Override
public int hashCode() {
final int prime = 31;
diff --git a/service/src/com/android/car/pm/CarAppMetadataReader.java b/service/src/com/android/car/pm/CarAppMetadataReader.java
index 7c1e115..648fded 100644
--- a/service/src/com/android/car/pm/CarAppMetadataReader.java
+++ b/service/src/com/android/car/pm/CarAppMetadataReader.java
@@ -51,18 +51,19 @@
* @return Array of DO activity names in the given package
*/
@Nullable
- public static String[] findDistractionOptimizedActivities(Context context, String packageName)
- throws NameNotFoundException {
+ public static String[] findDistractionOptimizedActivitiesAsUser(Context context,
+ String packageName, int userId) throws NameNotFoundException {
final PackageManager pm = context.getPackageManager();
// Check if any of the activities in the package are DO by checking all the
// <activity> elements.
PackageInfo pkgInfo =
- pm.getPackageInfo(
+ pm.getPackageInfoAsUser(
packageName, PackageManager.GET_ACTIVITIES
| PackageManager.GET_META_DATA
| PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ userId);
if (pkgInfo == null) {
return null;
}
diff --git a/service/src/com/android/car/pm/CarPackageManagerService.java b/service/src/com/android/car/pm/CarPackageManagerService.java
index 08e13e1..7615d28 100644
--- a/service/src/com/android/car/pm/CarPackageManagerService.java
+++ b/service/src/com/android/car/pm/CarPackageManagerService.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
import android.car.Car;
import android.car.content.pm.AppBlockingPackageInfo;
@@ -48,7 +49,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.Process;
-import android.text.TextUtils;
+import android.os.UserHandle;
import android.text.format.DateFormat;
import android.util.ArraySet;
import android.util.Log;
@@ -87,6 +88,7 @@
private final Context mContext;
private final SystemActivityMonitoringService mSystemActivityMonitoringService;
private final PackageManager mPackageManager;
+ private final ActivityManager mActivityManager;
private final HandlerThread mHandlerThread;
private final PackageHandler mHandler;
@@ -110,8 +112,6 @@
private HashMap<String, AppBlockingPackageInfoWrapper> mActivityWhitelistMap = new HashMap<>();
// The list corresponding to the one configured in <activityBlacklist>
@GuardedBy("this")
- private HashMap<String, AppBlockingPackageInfoWrapper> mActivityBlacklistMap = new HashMap<>();
- @GuardedBy("this")
private LinkedList<AppBlockingPolicyProxy> mProxies;
@GuardedBy("this")
@@ -179,6 +179,7 @@
mCarUxRestrictionsService = uxRestrictionsService;
mSystemActivityMonitoringService = systemActivityMonitoringService;
mPackageManager = mContext.getPackageManager();
+ mActivityManager = mContext.getSystemService(ActivityManager.class);
mUxRestrictionsListener = new UxRestrictionsListener(uxRestrictionsService);
mHandlerThread = new HandlerThread(CarLog.TAG_PACKAGE);
mHandlerThread.start();
@@ -318,8 +319,7 @@
return wrapper.info;
}
}
- AppBlockingPackageInfoWrapper wrapper = mActivityBlacklistMap.get(packageName);
- return (wrapper != null) ? wrapper.info : null;
+ return null;
}
@GuardedBy("this")
@@ -374,7 +374,6 @@
}
mHasParsedPackages = false;
mActivityWhitelistMap.clear();
- mActivityBlacklistMap.clear();
mClientPolicies.clear();
if (mProxies != null) {
for (AppBlockingPolicyProxy proxy : mProxies) {
@@ -382,7 +381,7 @@
}
mProxies.clear();
}
- wakeupClientsWaitingForPolicySetitngLocked();
+ wakeupClientsWaitingForPolicySettingLocked();
}
mContext.unregisterReceiver(mPackageParsingEventReceiver);
mContext.unregisterReceiver(mUserSwitchedEventReceiver);
@@ -401,7 +400,8 @@
pkgParseIntent.addAction(action);
}
pkgParseIntent.addDataScheme("package");
- mContext.registerReceiver(mPackageParsingEventReceiver, pkgParseIntent);
+ mContext.registerReceiverAsUser(mPackageParsingEventReceiver, UserHandle.ALL,
+ pkgParseIntent, null, null);
try {
// TODO(128456985): register listener for each display in order to
// properly launch blocking screens.
@@ -418,8 +418,8 @@
}
private void doParseInstalledPackages() {
- generateActivityWhitelistMap();
- generateActivityBlacklistMap();
+ int userId = mActivityManager.getCurrentUser();
+ generateActivityWhitelistMap(userId);
synchronized (this) {
mHasParsedPackages = true;
}
@@ -432,7 +432,7 @@
}
@GuardedBy("this")
- private void wakeupClientsWaitingForPolicySetitngLocked() {
+ private void wakeupClientsWaitingForPolicySettingLocked() {
for (CarAppBlockingPolicy waitingPolicy : mWaitingPolicies) {
synchronized (waitingPolicy) {
waitingPolicy.notifyAll();
@@ -443,7 +443,7 @@
private void doSetPolicy() {
synchronized (this) {
- wakeupClientsWaitingForPolicySetitngLocked();
+ wakeupClientsWaitingForPolicySettingLocked();
}
blockTopActivitiesIfNecessary();
}
@@ -559,12 +559,36 @@
* Generate a map of whitelisted packages and activities of the form {pkgName, Whitelisted
* activities}. The whitelist information can come from a configuration XML resource or from
* the apps marking their activities as distraction optimized.
+ *
+ * @param userId Generate whitelist based on packages installed for this user.
*/
- private void generateActivityWhitelistMap() {
- HashMap<String, AppBlockingPackageInfoWrapper> activityWhitelist = new HashMap<>();
-
+ private void generateActivityWhitelistMap(int userId) {
// Get the apps/activities that are whitelisted in the configuration XML resources.
- HashMap<String, Set<String>> configWhitelist = new HashMap<>();
+ Map<String, Set<String>> configWhitelist = generateConfigWhitelist();
+ Map<String, Set<String>> configBlacklist = generateConfigBlacklist();
+
+ Map<String, AppBlockingPackageInfoWrapper> activityWhitelist =
+ generateActivityWhitelistAsUser(UserHandle.USER_SYSTEM,
+ configWhitelist, configBlacklist);
+ // Also parse packages for current user.
+ if (userId != UserHandle.USER_SYSTEM) {
+ Map<String, AppBlockingPackageInfoWrapper> userWhitelistedPackages =
+ generateActivityWhitelistAsUser(userId, configWhitelist, configBlacklist);
+ for (String packageName : userWhitelistedPackages.keySet()) {
+ if (activityWhitelist.containsKey(packageName)) {
+ continue;
+ }
+ activityWhitelist.put(packageName, userWhitelistedPackages.get(packageName));
+ }
+ }
+ synchronized (this) {
+ mActivityWhitelistMap.clear();
+ mActivityWhitelistMap.putAll(activityWhitelist);
+ }
+ }
+
+ private Map<String, Set<String>> generateConfigWhitelist() {
+ Map<String, Set<String>> configWhitelist = new HashMap<>();
mConfiguredWhitelist = mContext.getString(R.string.activityWhitelist);
if (mConfiguredWhitelist == null) {
if (DBG_POLICY_CHECK) {
@@ -572,6 +596,7 @@
}
}
parseConfigList(mConfiguredWhitelist, configWhitelist);
+
mConfiguredSystemWhitelist = mContext.getString(R.string.systemActivityWhitelist);
if (mConfiguredSystemWhitelist == null) {
if (DBG_POLICY_CHECK) {
@@ -588,11 +613,43 @@
configWhitelist.put(mActivityBlockingActivity.getPackageName(), defaultActivity);
}
- List<PackageInfo> packages = mPackageManager.getInstalledPackages(
+ return configWhitelist;
+ }
+
+ private Map<String, Set<String>> generateConfigBlacklist() {
+ Map<String, Set<String>> configBlacklist = new HashMap<>();
+ mConfiguredBlacklist = mContext.getString(R.string.activityBlacklist);
+ if (mConfiguredBlacklist == null) {
+ if (DBG_POLICY_CHECK) {
+ Log.d(CarLog.TAG_PACKAGE, "Null blacklist in config");
+ }
+ }
+ parseConfigList(mConfiguredBlacklist, configBlacklist);
+
+ return configBlacklist;
+ }
+
+ /**
+ * Generates whitelisted activities based on packages installed for system user and current
+ * user (if different). Factors affecting whitelist:
+ * - whitelist from resource config;
+ * - activity declared as Distraction Optimized (D.O.) in manifest;
+ * - blacklist from resource config - package/activity blacklisted will not exist
+ * in returned whitelist.
+ *
+ * @param userId Parse packages installed for user.
+ * @param configWhitelist Whitelist from config.
+ * @param configBlacklist Blacklist from config.
+ */
+ private Map<String, AppBlockingPackageInfoWrapper> generateActivityWhitelistAsUser(int userId,
+ Map<String, Set<String>> configWhitelist, Map<String, Set<String>> configBlacklist) {
+ HashMap<String, AppBlockingPackageInfoWrapper> activityWhitelist = new HashMap<>();
+
+ List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(
PackageManager.GET_SIGNATURES | PackageManager.GET_ACTIVITIES
| PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
-
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ userId);
for (PackageInfo info : packages) {
if (info.applicationInfo == null) {
continue;
@@ -606,8 +663,8 @@
flags = AppBlockingPackageInfo.FLAG_SYSTEM_APP;
}
- /* 1. Check if all or some of this app is in the <activityWhitelist>
- in config.xml */
+ /* 1. Check if all or some of this app is in the <activityWhitelist> or
+ <systemActivityWhitelist> in config.xml */
Set<String> configActivitiesForPackage = configWhitelist.get(info.packageName);
if (configActivitiesForPackage != null) {
if (DBG_POLICY_CHECK) {
@@ -662,8 +719,9 @@
}
try {
- String[] doActivities = CarAppMetadataReader.findDistractionOptimizedActivities(
- mContext, info.packageName);
+ String[] doActivities =
+ CarAppMetadataReader.findDistractionOptimizedActivitiesAsUser(
+ mContext, info.packageName, userId);
if (doActivities != null) {
// Some of the activities in this app are Distraction Optimized.
if (DBG_POLICY_CHECK) {
@@ -685,6 +743,17 @@
continue;
}
+ /* 3. Check if parsed activity is in <activityBlacklist> in config.xml. Anything
+ in blacklist should not be whitelisted, either as D.O. or by config. */
+ if (configBlacklist.containsKey(info.packageName)) {
+ Set<String> configBlacklistActivities = configBlacklist.get(info.packageName);
+ if (configBlacklistActivities.isEmpty()) {
+ // Whole package should be blacklisted.
+ continue;
+ }
+ activities.removeAll(configBlacklistActivities);
+ }
+
Signature[] signatures;
signatures = info.signatures;
AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(
@@ -694,10 +763,7 @@
appBlockingInfo, true);
activityWhitelist.put(info.packageName, wrapper);
}
- synchronized (this) {
- mActivityWhitelistMap.clear();
- mActivityWhitelistMap.putAll(activityWhitelist);
- }
+ return activityWhitelist;
}
private boolean isDebugBuild() {
@@ -705,74 +771,6 @@
}
/**
- * Generate a map of blacklisted packages and activities of the form {pkgName, Blacklisted
- * activities}. The blacklist information comes from a configuration XML resource.
- */
- private void generateActivityBlacklistMap() {
- HashMap<String, AppBlockingPackageInfoWrapper> activityBlacklist = new HashMap<>();
-
- // Parse blacklisted activities.
- Map<String, Set<String>> configBlacklist = new HashMap<>();
- mConfiguredBlacklist = mContext.getString(R.string.activityBlacklist);
- if (mConfiguredBlacklist == null) {
- if (DBG_POLICY_CHECK) {
- Log.d(CarLog.TAG_PACKAGE, "Null blacklist in config");
- }
- }
- parseConfigList(mConfiguredBlacklist, configBlacklist);
-
- for (String pkg : configBlacklist.keySet()) {
- if (TextUtils.isEmpty(pkg)) {
- // This means there is nothing to blacklist
- Log.d(CarLog.TAG_PACKAGE, "Empty string in blacklist pkg");
- continue;
- }
- int flags = 0;
- PackageInfo pkgInfo;
- Set<String> activities = new ArraySet<>();
- try {
- pkgInfo = mPackageManager.getPackageInfo(
- pkg, PackageManager.GET_ACTIVITIES
- | PackageManager.GET_SIGNING_CERTIFICATES
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- } catch (NameNotFoundException e) {
- Log.e(CarLog.TAG_PACKAGE, pkg + " not found to blacklist ", e);
- continue;
- }
-
- if (pkgInfo.applicationInfo.isSystemApp()
- || pkgInfo.applicationInfo.isUpdatedSystemApp()) {
- flags |= AppBlockingPackageInfo.FLAG_SYSTEM_APP;
- }
- Set<String> configActivities = configBlacklist.get(pkg);
- if (configActivities.size() == 0) {
- // whole package
- flags |= AppBlockingPackageInfo.FLAG_WHOLE_ACTIVITY;
- List<String> activitiesInPackage = getActivitiesInPackage(pkgInfo);
- if (activitiesInPackage != null && !activitiesInPackage.isEmpty()) {
- activities.addAll(activitiesInPackage);
- }
- } else {
- activities.addAll(configActivities);
- }
-
- if (activities.isEmpty()) {
- continue;
- }
- AppBlockingPackageInfo appBlockingInfo = new AppBlockingPackageInfo(pkg, 0, 0, flags,
- pkgInfo.signatures, activities.toArray(new String[activities.size()]));
- AppBlockingPackageInfoWrapper wrapper = new AppBlockingPackageInfoWrapper(
- appBlockingInfo, true);
- activityBlacklist.put(pkg, wrapper);
- }
- synchronized (this) {
- mActivityBlacklistMap.clear();
- mActivityBlacklistMap.putAll(activityBlacklist);
- }
- }
-
- /**
* Parses the given resource and updates the input map of packages and activities.
*
* Key is package name and value is list of activities. Empty set implies whole package is
@@ -917,10 +915,6 @@
for (AppBlockingPackageInfoWrapper wrapper : mActivityWhitelistMap.values()) {
sb.append(wrapper.toString() + "\n");
}
- sb.append("**System Black list**\n");
- for (AppBlockingPackageInfoWrapper wrapper : mActivityBlacklistMap.values()) {
- sb.append(wrapper.toString() + "\n");
- }
}
sb.append("**Client Policies**\n");
for (Entry<String, ClientPolicy> entry : mClientPolicies.entrySet()) {
@@ -943,6 +937,9 @@
sb.append("**Whitelist string in resource**\n");
sb.append(mConfiguredWhitelist + "\n");
+ sb.append("**System whitelist string in resource**\n");
+ sb.append(mConfiguredSystemWhitelist + "\n");
+
sb.append("**Blacklist string in resource**\n");
sb.append(mConfiguredBlacklist + "\n");
@@ -1091,7 +1088,8 @@
@Nullable
public String[] getDistractionOptimizedActivities(String pkgName) {
try {
- return CarAppMetadataReader.findDistractionOptimizedActivities(mContext, pkgName);
+ return CarAppMetadataReader.findDistractionOptimizedActivitiesAsUser(mContext, pkgName,
+ mActivityManager.getCurrentUser());
} catch (NameNotFoundException e) {
return null;
}
@@ -1154,6 +1152,9 @@
}
private void requestParsingInstalledPkgs(long delayMs) {
+ // Parse packages for current user.
+ removeMessages(MSG_PARSE_PKG);
+
Message msg = obtainMessage(MSG_PARSE_PKG);
if (delayMs == 0) {
sendMessage(msg);
@@ -1169,7 +1170,6 @@
doHandleInit();
break;
case MSG_PARSE_PKG:
- removeMessages(MSG_PARSE_PKG);
doParseInstalledPackages();
break;
case MSG_SET_POLICY: