diff options
| author | 2016-01-12 03:16:22 +0000 | |
|---|---|---|
| committer | 2016-01-12 03:16:22 +0000 | |
| commit | 9229ee595988c66f1c59409a963fef88b2c30e03 (patch) | |
| tree | 88d17732d69628f96c9cd2b72ff8ce176f53173e | |
| parent | 8f124a9a97cb46d9c6db88432d66e9171cd7e456 (diff) | |
| parent | 2bd31dbd023a11d90061c7b6831dd06454c928af (diff) | |
Merge "Install non-EA providers once user is unlocked."
6 files changed, 186 insertions, 150 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 134966248f94..a0df610c7428 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -463,92 +463,60 @@ public class PackageParser { p.featureGroups.toArray(pi.featureGroups); } } - if ((flags&PackageManager.GET_ACTIVITIES) != 0) { - int N = p.activities.size(); + if ((flags & PackageManager.GET_ACTIVITIES) != 0) { + final int N = p.activities.size(); if (N > 0) { - if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.activities = new ActivityInfo[N]; - } else { - int num = 0; - for (int i=0; i<N; i++) { - if (p.activities.get(i).info.enabled) num++; - } - pi.activities = new ActivityInfo[num]; - } - for (int i=0, j=0; i<N; i++) { - final Activity activity = p.activities.get(i); - if (activity.info.enabled - || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.activities[j++] = generateActivityInfo(p.activities.get(i), flags, - state, userId); + int num = 0; + final ActivityInfo[] res = new ActivityInfo[N]; + for (int i = 0; i < N; i++) { + final Activity a = p.activities.get(i); + if (state.isMatch(a.info, flags)) { + res[num++] = generateActivityInfo(a, flags, state, userId); } } + pi.activities = ArrayUtils.trimToSize(res, num); } } - if ((flags&PackageManager.GET_RECEIVERS) != 0) { - int N = p.receivers.size(); + if ((flags & PackageManager.GET_RECEIVERS) != 0) { + final int N = p.receivers.size(); if (N > 0) { - if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.receivers = new ActivityInfo[N]; - } else { - int num = 0; - for (int i=0; i<N; i++) { - if (p.receivers.get(i).info.enabled) num++; - } - pi.receivers = new ActivityInfo[num]; - } - for (int i=0, j=0; i<N; i++) { - final Activity activity = p.receivers.get(i); - if (activity.info.enabled - || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.receivers[j++] = generateActivityInfo(p.receivers.get(i), flags, - state, userId); + int num = 0; + final ActivityInfo[] res = new ActivityInfo[N]; + for (int i = 0; i < N; i++) { + final Activity a = p.receivers.get(i); + if (state.isMatch(a.info, flags)) { + res[num++] = generateActivityInfo(a, flags, state, userId); } } + pi.receivers = ArrayUtils.trimToSize(res, num); } } - if ((flags&PackageManager.GET_SERVICES) != 0) { - int N = p.services.size(); + if ((flags & PackageManager.GET_SERVICES) != 0) { + final int N = p.services.size(); if (N > 0) { - if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.services = new ServiceInfo[N]; - } else { - int num = 0; - for (int i=0; i<N; i++) { - if (p.services.get(i).info.enabled) num++; - } - pi.services = new ServiceInfo[num]; - } - for (int i=0, j=0; i<N; i++) { - final Service service = p.services.get(i); - if (service.info.enabled - || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.services[j++] = generateServiceInfo(p.services.get(i), flags, - state, userId); + int num = 0; + final ServiceInfo[] res = new ServiceInfo[N]; + for (int i = 0; i < N; i++) { + final Service s = p.services.get(i); + if (state.isMatch(s.info, flags)) { + res[num++] = generateServiceInfo(s, flags, state, userId); } } + pi.services = ArrayUtils.trimToSize(res, num); } } - if ((flags&PackageManager.GET_PROVIDERS) != 0) { - int N = p.providers.size(); + if ((flags & PackageManager.GET_PROVIDERS) != 0) { + final int N = p.providers.size(); if (N > 0) { - if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.providers = new ProviderInfo[N]; - } else { - int num = 0; - for (int i=0; i<N; i++) { - if (p.providers.get(i).info.enabled) num++; - } - pi.providers = new ProviderInfo[num]; - } - for (int i=0, j=0; i<N; i++) { - final Provider provider = p.providers.get(i); - if (provider.info.enabled - || (flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { - pi.providers[j++] = generateProviderInfo(p.providers.get(i), flags, - state, userId); + int num = 0; + final ProviderInfo[] res = new ProviderInfo[N]; + for (int i = 0; i < N; i++) { + final Provider pr = p.providers.get(i); + if (state.isMatch(pr.info, flags)) { + res[num++] = generateProviderInfo(pr, flags, state, userId); } } + pi.providers = ArrayUtils.trimToSize(res, num); } } if ((flags&PackageManager.GET_INSTRUMENTATION) != 0) { diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java index 91fdf7f71f10..38e0044ea74c 100644 --- a/core/java/android/content/pm/PackageUserState.java +++ b/core/java/android/content/pm/PackageUserState.java @@ -17,9 +17,20 @@ package android.content.pm; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; +import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; +import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; +import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; +import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE; +import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE; +import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import android.util.ArraySet; +import com.android.internal.util.ArrayUtils; + /** * Per-user state information about a package. * @hide @@ -58,12 +69,77 @@ public class PackageUserState { hidden = o.hidden; suspended = o.suspended; lastDisableAppCaller = o.lastDisableAppCaller; - disabledComponents = o.disabledComponents != null - ? new ArraySet<>(o.disabledComponents) : null; - enabledComponents = o.enabledComponents != null - ? new ArraySet<>(o.enabledComponents) : null; + disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents); + enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents); blockUninstall = o.blockUninstall; domainVerificationStatus = o.domainVerificationStatus; appLinkGeneration = o.appLinkGeneration; } + + /** + * Test if this package is installed. + */ + public boolean isInstalled(int flags) { + return (this.installed && !this.hidden) + || (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0; + } + + /** + * Test if the given component is considered installed, enabled and a match + * for the given flags. + */ + public boolean isMatch(ComponentInfo componentInfo, int flags) { + if (!isInstalled(flags)) return false; + if (!isEnabled(componentInfo, flags)) return false; + + if ((flags & MATCH_SYSTEM_ONLY) != 0) { + if (!componentInfo.applicationInfo.isSystemApp()) { + return false; + } + } + + final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0) + && !componentInfo.encryptionAware; + final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0) + && componentInfo.encryptionAware; + return matchesUnaware || matchesAware; + } + + /** + * Test if the given component is considered enabled. + */ + public boolean isEnabled(ComponentInfo componentInfo, int flags) { + if ((flags & MATCH_DISABLED_COMPONENTS) != 0) { + return true; + } + + // First check if the overall package is disabled; if the package is + // enabled then fall through to check specific component + switch (this.enabled) { + case COMPONENT_ENABLED_STATE_DISABLED: + case COMPONENT_ENABLED_STATE_DISABLED_USER: + return false; + case COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: + if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) == 0) { + return false; + } + case COMPONENT_ENABLED_STATE_DEFAULT: + if (!componentInfo.applicationInfo.enabled) { + return false; + } + case COMPONENT_ENABLED_STATE_ENABLED: + break; + } + + // Check if component has explicit state before falling through to + // the manifest default + if (ArrayUtils.contains(this.enabledComponents, componentInfo.name)) { + return true; + } + if (ArrayUtils.contains(this.disabledComponents, componentInfo.name)) { + return false; + } + + return componentInfo.enabled; + } } diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 16bf9dd2900b..ca1334c6e6cc 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -26,6 +26,7 @@ import libcore.util.EmptyArray; import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.Arrays; import java.util.Objects; /** @@ -372,6 +373,10 @@ public class ArrayUtils { return (array != null) ? array.clone() : null; } + public static @Nullable <T> ArraySet<T> cloneOrNull(@Nullable ArraySet<T> array) { + return (array != null) ? new ArraySet<T>(array) : null; + } + public static @NonNull <T> ArraySet<T> add(@Nullable ArraySet<T> cur, T val) { if (cur == null) { cur = new ArraySet<>(); @@ -420,6 +425,16 @@ public class ArrayUtils { return (cur != null) ? cur.contains(val) : false; } + public static @Nullable <T> T[] trimToSize(@Nullable T[] array, int size) { + if (array == null || size == 0) { + return null; + } else if (array.length == size) { + return array; + } else { + return Arrays.copyOf(array, size); + } + } + /** * Returns true if the two ArrayLists are equal with respect to the objects they contain. * The objects must be in the same order and be reference equal (== not .equals()). diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index a4b13ed96e00..4f75810678a5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -255,7 +255,9 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT; import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; +import static android.content.pm.PackageManager.GET_PROVIDERS; import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING; +import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -1954,8 +1956,10 @@ public final class ActivityManagerService extends ActivityManagerNative break; } case SYSTEM_USER_UNLOCK_MSG: { - mSystemServiceManager.unlockUser(msg.arg1); - mRecentTasks.cleanupLocked(msg.arg1); + final int userId = msg.arg1; + mSystemServiceManager.unlockUser(userId); + mRecentTasks.cleanupLocked(userId); + installEncryptionUnawareProviders(userId); break; } case SYSTEM_USER_CURRENT_MSG: { @@ -10824,6 +10828,41 @@ public final class ActivityManagerService extends ActivityManagerNative } /** + * When a user is unlocked, we need to install encryption-unaware providers + * belonging to any running apps. + */ + private void installEncryptionUnawareProviders(int userId) { + synchronized (this) { + final int NP = mProcessNames.getMap().size(); + for (int ip = 0; ip < NP; ip++) { + final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip); + final int NA = apps.size(); + for (int ia = 0; ia < NA; ia++) { + final ProcessRecord app = apps.valueAt(ia); + if (app.userId != userId || app.thread == null) continue; + + final int NG = app.pkgList.size(); + for (int ig = 0; ig < NG; ig++) { + try { + final String pkgName = app.pkgList.keyAt(ig); + final PackageInfo pkgInfo = AppGlobals.getPackageManager() + .getPackageInfo(pkgName, + GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE, userId); + if (pkgInfo != null && !ArrayUtils.isEmpty(pkgInfo.providers)) { + for (ProviderInfo provInfo : pkgInfo.providers) { + Log.v(TAG, "Installing " + provInfo); + app.thread.scheduleInstallProvider(provInfo); + } + } + } catch (RemoteException ignored) { + } + } + } + } + } + } + + /** * Allows apps to retrieve the MIME type of a URI. * If an app is in the same user as the ContentProvider, or if it is allowed to interact across * users, then it does not need permission to access the ContentProvider. diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 41627fd58f01..e3ed0c136d56 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -3121,7 +3121,7 @@ public class PackageManagerService extends IPackageManager.Stub { /** * Update given flags based on encryption status of current user. */ - private int updateFlagsForEncryption(int flags, int userId) { + private int updateFlags(int flags, int userId) { if ((flags & (PackageManager.MATCH_ENCRYPTION_UNAWARE | PackageManager.MATCH_ENCRYPTION_AWARE)) != 0) { // Caller expressed an explicit opinion about what encryption @@ -3135,6 +3135,12 @@ public class PackageManagerService extends IPackageManager.Stub { flags |= PackageManager.MATCH_ENCRYPTION_AWARE; } } + + // Safe mode means we should ignore any third-party apps + if (mSafeMode) { + flags |= PackageManager.MATCH_SYSTEM_ONLY; + } + return flags; } @@ -3162,7 +3168,7 @@ public class PackageManagerService extends IPackageManager.Stub { Log.w(TAG, "Caller hasn't been triaged for missing apps; they asked about " + cookie + " with flags 0x" + Integer.toHexString(flags), new Throwable()); } - return updateFlagsForEncryption(flags, userId); + return updateFlags(flags, userId); } /** @@ -3194,7 +3200,7 @@ public class PackageManagerService extends IPackageManager.Stub { Log.w(TAG, "Caller hasn't been triaged for missing apps; they asked about " + cookie + " with flags 0x" + Integer.toHexString(flags), new Throwable()); } - return updateFlagsForEncryption(flags, userId); + return updateFlags(flags, userId); } /** @@ -5941,8 +5947,6 @@ public class PackageManagerService extends IPackageManager.Stub { : null; return ps != null && mSettings.isEnabledAndMatchLPr(provider.info, flags, userId) - && (!mSafeMode || (provider.info.applicationInfo.flags - &ApplicationInfo.FLAG_SYSTEM) != 0) ? PackageParser.generateProviderInfo(provider, flags, ps.readUserState(userId), userId) : null; @@ -5997,9 +6001,7 @@ public class PackageManagerService extends IPackageManager.Stub { && (processName == null || (p.info.processName.equals(processName) && UserHandle.isSameApp(p.info.applicationInfo.uid, uid))) - && mSettings.isEnabledAndMatchLPr(p.info, flags, userId) - && (!mSafeMode - || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) { + && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) { if (finalList == null) { finalList = new ArrayList<ProviderInfo>(3); } @@ -9265,10 +9267,6 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } final PackageParser.Activity activity = info.activity; - if (mSafeMode && (activity.info.applicationInfo.flags - &ApplicationInfo.FLAG_SYSTEM) == 0) { - return null; - } PackageSetting ps = (PackageSetting) activity.owner.mExtras; if (ps == null) { return null; @@ -9489,10 +9487,6 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } final PackageParser.Service service = info.service; - if (mSafeMode && (service.info.applicationInfo.flags - &ApplicationInfo.FLAG_SYSTEM) == 0) { - return null; - } PackageSetting ps = (PackageSetting) service.owner.mExtras; if (ps == null) { return null; @@ -9712,10 +9706,6 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } final PackageParser.Provider provider = info.provider; - if (mSafeMode && (provider.info.applicationInfo.flags - & ApplicationInfo.FLAG_SYSTEM) == 0) { - return null; - } PackageSetting ps = (PackageSetting) provider.owner.mExtras; if (ps == null) { return null; diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 3f9ce7a64aae..1a79d3c3e733 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3799,63 +3799,11 @@ final class Settings { } boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) { - return isEnabledLPr(componentInfo, flags, userId) - && isMatchLPr(componentInfo, flags); - } - - private boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) { - if ((flags & MATCH_DISABLED_COMPONENTS) != 0) { - return true; - } - final PackageSetting packageSettings = mPackages.get(componentInfo.packageName); - if (PackageManagerService.DEBUG_SETTINGS) { - Log.v(PackageManagerService.TAG, "isEnabledLock - packageName = " - + componentInfo.packageName + " componentName = " + componentInfo.name); - Log.v(PackageManagerService.TAG, "enabledComponents: " - + compToString(packageSettings.getEnabledComponents(userId))); - Log.v(PackageManagerService.TAG, "disabledComponents: " - + compToString(packageSettings.getDisabledComponents(userId))); - } - if (packageSettings == null) { - return false; - } - PackageUserState ustate = packageSettings.readUserState(userId); - if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) != 0) { - if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { - return true; - } - } - if (ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED - || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_USER - || ustate.enabled == COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED - || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled - && ustate.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) { - return false; - } - if (ustate.enabledComponents != null - && ustate.enabledComponents.contains(componentInfo.name)) { - return true; - } - if (ustate.disabledComponents != null - && ustate.disabledComponents.contains(componentInfo.name)) { - return false; - } - return componentInfo.enabled; - } - - private boolean isMatchLPr(ComponentInfo componentInfo, int flags) { - if ((flags & MATCH_SYSTEM_ONLY) != 0) { - final PackageSetting ps = mPackages.get(componentInfo.packageName); - if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { - return false; - } - } + final PackageSetting ps = mPackages.get(componentInfo.packageName); + if (ps == null) return false; - final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0) - && !componentInfo.encryptionAware; - final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0) - && componentInfo.encryptionAware; - return matchesUnaware || matchesAware; + final PackageUserState userState = ps.readUserState(userId); + return userState.isMatch(componentInfo, flags); } String getInstallerPackageNameLPr(String packageName) { |