diff options
| -rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java | 128 | ||||
| -rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java | 180 |
2 files changed, 142 insertions, 166 deletions
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 081f3f673702..6fefbf980dc5 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -16,7 +16,6 @@ package com.android.providers.settings; -import static android.os.Process.INVALID_UID; import static android.os.Process.ROOT_UID; import static android.os.Process.SHELL_UID; import static android.os.Process.SYSTEM_UID; @@ -364,6 +363,11 @@ public class SettingsProvider extends ContentProvider { mHandler = new Handler(mHandlerThread.getLooper()); mSettingsRegistry = new SettingsRegistry(); } + SettingsState.cacheSystemPackageNamesAndSystemSignature(getContext()); + synchronized (mLock) { + mSettingsRegistry.migrateAllLegacySettingsIfNeededLocked(); + mSettingsRegistry.syncSsaidTableOnStartLocked(); + } mHandler.post(() -> { registerBroadcastReceivers(); startWatchingUserRestrictionChanges(); @@ -2496,8 +2500,6 @@ public class SettingsProvider extends ContentProvider { mHandler = new MyHandler(getContext().getMainLooper()); mGenerationRegistry = new GenerationRegistry(mLock); mBackupManager = new BackupManager(getContext()); - migrateAllLegacySettingsIfNeeded(); - syncSsaidTableOnStart(); } private void generateUserKeyLocked(int userId) { @@ -2584,38 +2586,36 @@ public class SettingsProvider extends ContentProvider { return getSettingLocked(SETTINGS_TYPE_SSAID, userId, uid); } - public void syncSsaidTableOnStart() { - synchronized (mLock) { - // Verify that each user's packages and ssaid's are in sync. - for (UserInfo user : mUserManager.getAliveUsers()) { - // Get all uids for the user's packages. - final List<PackageInfo> packages; - try { - packages = mPackageManager.getInstalledPackages( + private void syncSsaidTableOnStartLocked() { + // Verify that each user's packages and ssaid's are in sync. + for (UserInfo user : mUserManager.getAliveUsers()) { + // Get all uids for the user's packages. + final List<PackageInfo> packages; + try { + packages = mPackageManager.getInstalledPackages( PackageManager.MATCH_UNINSTALLED_PACKAGES, user.id).getList(); - } catch (RemoteException e) { - throw new IllegalStateException("Package manager not available"); - } - final Set<String> appUids = new HashSet<>(); - for (PackageInfo info : packages) { - appUids.add(Integer.toString(info.applicationInfo.uid)); - } + } catch (RemoteException e) { + throw new IllegalStateException("Package manager not available"); + } + final Set<String> appUids = new HashSet<>(); + for (PackageInfo info : packages) { + appUids.add(Integer.toString(info.applicationInfo.uid)); + } - // Get all uids currently stored in the user's ssaid table. - final Set<String> ssaidUids = new HashSet<>( - getSettingsNamesLocked(SETTINGS_TYPE_SSAID, user.id)); - ssaidUids.remove(SSAID_USER_KEY); + // Get all uids currently stored in the user's ssaid table. + final Set<String> ssaidUids = new HashSet<>( + getSettingsNamesLocked(SETTINGS_TYPE_SSAID, user.id)); + ssaidUids.remove(SSAID_USER_KEY); - // Perform a set difference for the appUids and ssaidUids. - ssaidUids.removeAll(appUids); + // Perform a set difference for the appUids and ssaidUids. + ssaidUids.removeAll(appUids); - // If there are ssaidUids left over they need to be removed from the table. - final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, - user.id); - for (String uid : ssaidUids) { - ssaidSettings.deleteSettingLocked(uid); - } + // If there are ssaidUids left over they need to be removed from the table. + final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, + user.id); + for (String uid : ssaidUids) { + ssaidSettings.deleteSettingLocked(uid); } } } @@ -2908,7 +2908,7 @@ public class SettingsProvider extends ContentProvider { boolean someSettingChanged = false; Setting setting = settingsState.getSettingLocked(name); if (!SettingsState.isSystemPackage(getContext(), - setting.getPackageName(), INVALID_UID, userId)) { + setting.getPackageName())) { if (prefix != null && !setting.getName().startsWith(prefix)) { continue; } @@ -2928,7 +2928,7 @@ public class SettingsProvider extends ContentProvider { boolean someSettingChanged = false; Setting setting = settingsState.getSettingLocked(name); if (!SettingsState.isSystemPackage(getContext(), - setting.getPackageName(), INVALID_UID, userId)) { + setting.getPackageName())) { if (prefix != null && !setting.getName().startsWith(prefix)) { continue; } @@ -3006,40 +3006,38 @@ public class SettingsProvider extends ContentProvider { return mSettingsStates.get(key); } - private void migrateAllLegacySettingsIfNeeded() { - synchronized (mLock) { - final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); - File globalFile = getSettingsFile(key); - if (SettingsState.stateFileExists(globalFile)) { - return; - } + private void migrateAllLegacySettingsIfNeededLocked() { + final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); + File globalFile = getSettingsFile(key); + if (SettingsState.stateFileExists(globalFile)) { + return; + } - mSettingsCreationBuildId = Build.ID; + mSettingsCreationBuildId = Build.ID; - final long identity = Binder.clearCallingIdentity(); - try { - List<UserInfo> users = mUserManager.getAliveUsers(); + final long identity = Binder.clearCallingIdentity(); + try { + List<UserInfo> users = mUserManager.getAliveUsers(); - final int userCount = users.size(); - for (int i = 0; i < userCount; i++) { - final int userId = users.get(i).id; + final int userCount = users.size(); + for (int i = 0; i < userCount; i++) { + final int userId = users.get(i).id; - DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId); - SQLiteDatabase database = dbHelper.getWritableDatabase(); - migrateLegacySettingsForUserLocked(dbHelper, database, userId); + DatabaseHelper dbHelper = new DatabaseHelper(getContext(), userId); + SQLiteDatabase database = dbHelper.getWritableDatabase(); + migrateLegacySettingsForUserLocked(dbHelper, database, userId); - // Upgrade to the latest version. - UpgradeController upgrader = new UpgradeController(userId); - upgrader.upgradeIfNeededLocked(); + // Upgrade to the latest version. + UpgradeController upgrader = new UpgradeController(userId); + upgrader.upgradeIfNeededLocked(); - // Drop from memory if not a running user. - if (!mUserManager.isUserRunning(new UserHandle(userId))) { - removeUserStateLocked(userId, false); - } + // Drop from memory if not a running user. + if (!mUserManager.isUserRunning(new UserHandle(userId))) { + removeUserStateLocked(userId, false); } - } finally { - Binder.restoreCallingIdentity(identity); } + } finally { + Binder.restoreCallingIdentity(identity); } } @@ -5033,19 +5031,9 @@ public class SettingsProvider extends ContentProvider { // In the upgrade case we pretend the call is made from the app // that made the last change to the setting to properly determine // whether the call has been made by a system component. - int callingUid = -1; - try { - callingUid = mPackageManager.getPackageUid(setting.getPackageName(), 0, userId); - } catch (RemoteException e) { - /* ignore - handled below */ - } - if (callingUid < 0) { - Slog.e(LOG_TAG, "Unknown package: " + setting.getPackageName()); - continue; - } try { - final boolean systemSet = SettingsState.isSystemPackage(getContext(), - setting.getPackageName(), callingUid, userId); + final boolean systemSet = SettingsState.isSystemPackage( + getContext(), setting.getPackageName()); if (systemSet) { settings.insertSettingOverrideableByRestoreLocked(name, setting.getValue(), setting.getTag(), true, setting.getPackageName()); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java index 53d868ac0050..911ff9916d6c 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java @@ -17,14 +17,13 @@ package com.android.providers.settings; import static android.os.Process.FIRST_APPLICATION_UID; -import static android.os.Process.INVALID_UID; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.Signature; import android.os.Binder; import android.os.Build; import android.os.FileUtils; @@ -37,10 +36,10 @@ import android.provider.Settings; import android.providers.settings.SettingsOperationProto; import android.text.TextUtils; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.AtomicFile; import android.util.Base64; import android.util.Slog; -import android.util.SparseIntArray; import android.util.TimeUtils; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; @@ -149,13 +148,7 @@ final class SettingsState { private static final String NULL_VALUE = "null"; - private static final Object sLock = new Object(); - - @GuardedBy("sLock") - private static final SparseIntArray sSystemUids = new SparseIntArray(); - - @GuardedBy("sLock") - private static Signature sSystemSignature; + private static final ArraySet<String> sSystemPackages = new ArraySet<>(); private final Object mWriteLock = new Object(); @@ -641,7 +634,7 @@ final class SettingsState { /** * Dump historical operations as a proto buf. * - * @param proto The proto buf stream to dump to + * @param proto The proto buf stream to dump to * @param fieldId The repeated field ID to use to save an operation to. */ void dumpHistoricalOperations(@NonNull ProtoOutputStream proto, long fieldId) { @@ -1048,6 +1041,7 @@ final class SettingsState { /** * Uses AtomicFile to check if the file or its backup exists. + * * @param file The file to check for existence * @return whether the original or backup exist */ @@ -1307,9 +1301,9 @@ final class SettingsState { if (NULL_VALUE.equals(value)) { value = null; } - final boolean callerSystem = !forceNonSystemPackage && - !isNull() && isSystemPackage(mContext, packageName); + !isNull() && (isCalledFromSystem(packageName) + || isSystemPackage(mContext, packageName)); // Settings set by the system are always defaults. if (callerSystem) { setDefault = true; @@ -1434,98 +1428,92 @@ final class SettingsState { return sb.toString(); } - // Check if a specific package belonging to the caller is part of the system package. - public static boolean isSystemPackage(Context context, String packageName) { - final int callingUid = Binder.getCallingUid(); - final int callingUserId = UserHandle.getUserId(callingUid); - return isSystemPackage(context, packageName, callingUid, callingUserId); - } - - // Check if a specific package, uid, and user ID are part of the system package. - public static boolean isSystemPackage(Context context, String packageName, int uid, - int userId) { - synchronized (sLock) { - if (SYSTEM_PACKAGE_NAME.equals(packageName)) { - return true; - } - - // Shell and Root are not considered a part of the system - if (SHELL_PACKAGE_NAME.equals(packageName) - || ROOT_PACKAGE_NAME.equals(packageName)) { - return false; + // Cache the list of names of system packages. This is only called once on system boot. + public static void cacheSystemPackageNamesAndSystemSignature(@NonNull Context context) { + final PackageManager packageManager = context.getPackageManager(); + final long identity = Binder.clearCallingIdentity(); + try { + sSystemPackages.add(SYSTEM_PACKAGE_NAME); + // Cache SetupWizard package name. + final String setupWizPackageName = packageManager.getSetupWizardPackageName(); + if (setupWizPackageName != null) { + sSystemPackages.add(setupWizPackageName); } - - if (uid != INVALID_UID) { - // Native services running as a special UID get a pass - final int callingAppId = UserHandle.getAppId(uid); - if (callingAppId < FIRST_APPLICATION_UID) { - sSystemUids.put(callingAppId, callingAppId); - return true; + final List<PackageInfo> packageInfos = packageManager.getInstalledPackages(0); + final int installedPackagesCount = packageInfos.size(); + for (int i = 0; i < installedPackagesCount; i++) { + if (shouldAddToSystemPackages(packageInfos.get(i))) { + sSystemPackages.add(packageInfos.get(i).packageName); } } + } finally { + Binder.restoreCallingIdentity(identity); + } + } - final long identity = Binder.clearCallingIdentity(); - try { - try { - uid = context.getPackageManager().getPackageUidAsUser(packageName, 0, userId); - } catch (PackageManager.NameNotFoundException e) { - return false; - } - - // If the system or a special system UID (like telephony), done. - if (UserHandle.getAppId(uid) < FIRST_APPLICATION_UID) { - sSystemUids.put(uid, uid); - return true; - } - - // If already known system component, done. - if (sSystemUids.indexOfKey(uid) >= 0) { - return true; - } + private static boolean shouldAddToSystemPackages(@NonNull PackageInfo packageInfo) { + // Shell and Root are not considered a part of the system + if (isShellOrRoot(packageInfo.packageName)) { + return false; + } + // Already added + if (sSystemPackages.contains(packageInfo.packageName)) { + return false; + } + return isSystemPackage(packageInfo.applicationInfo); + } - // If SetupWizard, done. - String setupWizPackage = context.getPackageManager().getSetupWizardPackageName(); - if (packageName.equals(setupWizPackage)) { - sSystemUids.put(uid, uid); - return true; - } + private static boolean isShellOrRoot(@NonNull String packageName) { + return (SHELL_PACKAGE_NAME.equals(packageName) + || ROOT_PACKAGE_NAME.equals(packageName)); + } - // If a persistent system app, done. - PackageInfo packageInfo; - try { - packageInfo = context.getPackageManager().getPackageInfoAsUser( - packageName, PackageManager.GET_SIGNATURES, userId); - if ((packageInfo.applicationInfo.flags - & ApplicationInfo.FLAG_PERSISTENT) != 0 - && (packageInfo.applicationInfo.flags - & ApplicationInfo.FLAG_SYSTEM) != 0) { - sSystemUids.put(uid, uid); - return true; - } - } catch (PackageManager.NameNotFoundException e) { - return false; - } + private static boolean isCalledFromSystem(@NonNull String packageName) { + // Shell and Root are not considered a part of the system + if (isShellOrRoot(packageName)) { + return false; + } + final int callingUid = Binder.getCallingUid(); + // Native services running as a special UID get a pass + final int callingAppId = UserHandle.getAppId(callingUid); + return (callingAppId < FIRST_APPLICATION_UID); + } - // Last check if system signed. - if (sSystemSignature == null) { - try { - sSystemSignature = context.getPackageManager().getPackageInfoAsUser( - SYSTEM_PACKAGE_NAME, PackageManager.GET_SIGNATURES, - UserHandle.USER_SYSTEM).signatures[0]; - } catch (PackageManager.NameNotFoundException e) { - /* impossible */ - return false; - } - } - if (sSystemSignature.equals(packageInfo.signatures[0])) { - sSystemUids.put(uid, uid); - return true; - } - } finally { - Binder.restoreCallingIdentity(identity); - } + public static boolean isSystemPackage(@NonNull Context context, @NonNull String packageName) { + // Check shell or root before trying to retrieve ApplicationInfo to fail fast + if (isShellOrRoot(packageName)) { + return false; + } + // If it's a known system package or known to be platform signed + if (sSystemPackages.contains(packageName)) { + return true; + } + ApplicationInfo aInfo = null; + try { + // Notice that this makes a call to package manager inside the lock + aInfo = context.getPackageManager().getApplicationInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException ignored) { + } + return isSystemPackage(aInfo); + } + private static boolean isSystemPackage(@Nullable ApplicationInfo aInfo) { + if (aInfo == null) { return false; } + // If the system or a special system UID (like telephony), done. + if (aInfo.uid < FIRST_APPLICATION_UID) { + return true; + } + // If a persistent system app, done. + if ((aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0 + && (aInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + return true; + } + // Platform signed packages are considered to be from the system + if (aInfo.isSignedWithPlatformKey()) { + return true; + } + return false; } } |