Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +70 −58 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ 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; Loading Loading @@ -363,11 +364,6 @@ 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(); Loading Loading @@ -2503,6 +2499,8 @@ 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) { Loading Loading @@ -2589,7 +2587,8 @@ public class SettingsProvider extends ContentProvider { return getSettingLocked(SETTINGS_TYPE_SSAID, userId, uid); } private void syncSsaidTableOnStartLocked() { 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. Loading Loading @@ -2622,6 +2621,7 @@ public class SettingsProvider extends ContentProvider { } } } } public List<String> getSettingsNamesLocked(int type, int userId) { final int key = makeKey(type, userId); Loading Loading @@ -2911,7 +2911,7 @@ public class SettingsProvider extends ContentProvider { boolean someSettingChanged = false; Setting setting = settingsState.getSettingLocked(name); if (!SettingsState.isSystemPackage(getContext(), setting.getPackageName())) { setting.getPackageName(), INVALID_UID, userId)) { if (prefix != null && !setting.getName().startsWith(prefix)) { continue; } Loading @@ -2931,7 +2931,7 @@ public class SettingsProvider extends ContentProvider { boolean someSettingChanged = false; Setting setting = settingsState.getSettingLocked(name); if (!SettingsState.isSystemPackage(getContext(), setting.getPackageName())) { setting.getPackageName(), INVALID_UID, userId)) { if (prefix != null && !setting.getName().startsWith(prefix)) { continue; } Loading Loading @@ -3009,7 +3009,8 @@ public class SettingsProvider extends ContentProvider { return mSettingsStates.get(key); } private void migrateAllLegacySettingsIfNeededLocked() { private void migrateAllLegacySettingsIfNeeded() { synchronized (mLock) { final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); File globalFile = getSettingsFile(key); if (SettingsState.stateFileExists(globalFile)) { Loading Loading @@ -3043,6 +3044,7 @@ public class SettingsProvider extends ContentProvider { Binder.restoreCallingIdentity(identity); } } } private void migrateLegacySettingsForUserIfNeededLocked(int userId) { // Every user has secure settings and if no file we need to migrate. Loading Loading @@ -5034,9 +5036,19 @@ 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()); final boolean systemSet = SettingsState.isSystemPackage(getContext(), setting.getPackageName(), callingUid, userId); if (systemSet) { settings.insertSettingOverrideableByRestoreLocked(name, setting.getValue(), setting.getTag(), true, setting.getPackageName()); Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java +96 −84 Original line number Diff line number Diff line Loading @@ -17,13 +17,14 @@ 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; Loading @@ -36,10 +37,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; Loading Loading @@ -148,7 +149,13 @@ final class SettingsState { private static final String NULL_VALUE = "null"; private static final ArraySet<String> sSystemPackages = new ArraySet<>(); private static final Object sLock = new Object(); @GuardedBy("sLock") private static final SparseIntArray sSystemUids = new SparseIntArray(); @GuardedBy("sLock") private static Signature sSystemSignature; private final Object mWriteLock = new Object(); Loading Loading @@ -1041,7 +1048,6 @@ 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 */ Loading Loading @@ -1301,9 +1307,9 @@ final class SettingsState { if (NULL_VALUE.equals(value)) { value = null; } final boolean callerSystem = !forceNonSystemPackage && !isNull() && (isCalledFromSystem(packageName) || isSystemPackage(mContext, packageName)); !isNull() && isSystemPackage(mContext, packageName); // Settings set by the system are always defaults. if (callerSystem) { setDefault = true; Loading Loading @@ -1428,92 +1434,98 @@ final class SettingsState { return sb.toString(); } // 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); } 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); // 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; } private static boolean shouldAddToSystemPackages(@NonNull PackageInfo packageInfo) { // Shell and Root are not considered a part of the system if (isShellOrRoot(packageInfo.packageName)) { if (SHELL_PACKAGE_NAME.equals(packageName) || ROOT_PACKAGE_NAME.equals(packageName)) { return false; } // Already added if (sSystemPackages.contains(packageInfo.packageName)) { return false; } return isSystemPackage(packageInfo.applicationInfo); } private static boolean isShellOrRoot(@NonNull String packageName) { return (SHELL_PACKAGE_NAME.equals(packageName) || ROOT_PACKAGE_NAME.equals(packageName)); 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; } } private static boolean isCalledFromSystem(@NonNull String packageName) { // Shell and Root are not considered a part of the system if (isShellOrRoot(packageName)) { final long identity = Binder.clearCallingIdentity(); try { try { uid = context.getPackageManager().getPackageUidAsUser(packageName, 0, userId); } catch (PackageManager.NameNotFoundException e) { 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); // If the system or a special system UID (like telephony), done. if (UserHandle.getAppId(uid) < FIRST_APPLICATION_UID) { sSystemUids.put(uid, uid); return true; } 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 already known system component, done. if (sSystemUids.indexOfKey(uid) >= 0) { return true; } // If it's a known system package or known to be platform signed if (sSystemPackages.contains(packageName)) { // If SetupWizard, done. String setupWizPackage = context.getPackageManager().getSetupWizardPackageName(); if (packageName.equals(setupWizPackage)) { sSystemUids.put(uid, uid); return true; } ApplicationInfo aInfo = null; // If a persistent system app, done. PackageInfo packageInfo; try { // Notice that this makes a call to package manager inside the lock aInfo = context.getPackageManager().getApplicationInfo(packageName, 0); } catch (PackageManager.NameNotFoundException ignored) { 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; } return isSystemPackage(aInfo); } catch (PackageManager.NameNotFoundException e) { return false; } private static boolean isSystemPackage(@Nullable ApplicationInfo aInfo) { if (aInfo == null) { // 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 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) { if (sSystemSignature.equals(packageInfo.signatures[0])) { sSystemUids.put(uid, uid); return true; } // Platform signed packages are considered to be from the system if (aInfo.isSignedWithPlatformKey()) { return true; } finally { Binder.restoreCallingIdentity(identity); } return false; } } } Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +70 −58 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ 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; Loading Loading @@ -363,11 +364,6 @@ 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(); Loading Loading @@ -2503,6 +2499,8 @@ 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) { Loading Loading @@ -2589,7 +2587,8 @@ public class SettingsProvider extends ContentProvider { return getSettingLocked(SETTINGS_TYPE_SSAID, userId, uid); } private void syncSsaidTableOnStartLocked() { 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. Loading Loading @@ -2622,6 +2621,7 @@ public class SettingsProvider extends ContentProvider { } } } } public List<String> getSettingsNamesLocked(int type, int userId) { final int key = makeKey(type, userId); Loading Loading @@ -2911,7 +2911,7 @@ public class SettingsProvider extends ContentProvider { boolean someSettingChanged = false; Setting setting = settingsState.getSettingLocked(name); if (!SettingsState.isSystemPackage(getContext(), setting.getPackageName())) { setting.getPackageName(), INVALID_UID, userId)) { if (prefix != null && !setting.getName().startsWith(prefix)) { continue; } Loading @@ -2931,7 +2931,7 @@ public class SettingsProvider extends ContentProvider { boolean someSettingChanged = false; Setting setting = settingsState.getSettingLocked(name); if (!SettingsState.isSystemPackage(getContext(), setting.getPackageName())) { setting.getPackageName(), INVALID_UID, userId)) { if (prefix != null && !setting.getName().startsWith(prefix)) { continue; } Loading Loading @@ -3009,7 +3009,8 @@ public class SettingsProvider extends ContentProvider { return mSettingsStates.get(key); } private void migrateAllLegacySettingsIfNeededLocked() { private void migrateAllLegacySettingsIfNeeded() { synchronized (mLock) { final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM); File globalFile = getSettingsFile(key); if (SettingsState.stateFileExists(globalFile)) { Loading Loading @@ -3043,6 +3044,7 @@ public class SettingsProvider extends ContentProvider { Binder.restoreCallingIdentity(identity); } } } private void migrateLegacySettingsForUserIfNeededLocked(int userId) { // Every user has secure settings and if no file we need to migrate. Loading Loading @@ -5034,9 +5036,19 @@ 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()); final boolean systemSet = SettingsState.isSystemPackage(getContext(), setting.getPackageName(), callingUid, userId); if (systemSet) { settings.insertSettingOverrideableByRestoreLocked(name, setting.getValue(), setting.getTag(), true, setting.getPackageName()); Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java +96 −84 Original line number Diff line number Diff line Loading @@ -17,13 +17,14 @@ 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; Loading @@ -36,10 +37,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; Loading Loading @@ -148,7 +149,13 @@ final class SettingsState { private static final String NULL_VALUE = "null"; private static final ArraySet<String> sSystemPackages = new ArraySet<>(); private static final Object sLock = new Object(); @GuardedBy("sLock") private static final SparseIntArray sSystemUids = new SparseIntArray(); @GuardedBy("sLock") private static Signature sSystemSignature; private final Object mWriteLock = new Object(); Loading Loading @@ -1041,7 +1048,6 @@ 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 */ Loading Loading @@ -1301,9 +1307,9 @@ final class SettingsState { if (NULL_VALUE.equals(value)) { value = null; } final boolean callerSystem = !forceNonSystemPackage && !isNull() && (isCalledFromSystem(packageName) || isSystemPackage(mContext, packageName)); !isNull() && isSystemPackage(mContext, packageName); // Settings set by the system are always defaults. if (callerSystem) { setDefault = true; Loading Loading @@ -1428,92 +1434,98 @@ final class SettingsState { return sb.toString(); } // 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); } 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); // 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; } private static boolean shouldAddToSystemPackages(@NonNull PackageInfo packageInfo) { // Shell and Root are not considered a part of the system if (isShellOrRoot(packageInfo.packageName)) { if (SHELL_PACKAGE_NAME.equals(packageName) || ROOT_PACKAGE_NAME.equals(packageName)) { return false; } // Already added if (sSystemPackages.contains(packageInfo.packageName)) { return false; } return isSystemPackage(packageInfo.applicationInfo); } private static boolean isShellOrRoot(@NonNull String packageName) { return (SHELL_PACKAGE_NAME.equals(packageName) || ROOT_PACKAGE_NAME.equals(packageName)); 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; } } private static boolean isCalledFromSystem(@NonNull String packageName) { // Shell and Root are not considered a part of the system if (isShellOrRoot(packageName)) { final long identity = Binder.clearCallingIdentity(); try { try { uid = context.getPackageManager().getPackageUidAsUser(packageName, 0, userId); } catch (PackageManager.NameNotFoundException e) { 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); // If the system or a special system UID (like telephony), done. if (UserHandle.getAppId(uid) < FIRST_APPLICATION_UID) { sSystemUids.put(uid, uid); return true; } 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 already known system component, done. if (sSystemUids.indexOfKey(uid) >= 0) { return true; } // If it's a known system package or known to be platform signed if (sSystemPackages.contains(packageName)) { // If SetupWizard, done. String setupWizPackage = context.getPackageManager().getSetupWizardPackageName(); if (packageName.equals(setupWizPackage)) { sSystemUids.put(uid, uid); return true; } ApplicationInfo aInfo = null; // If a persistent system app, done. PackageInfo packageInfo; try { // Notice that this makes a call to package manager inside the lock aInfo = context.getPackageManager().getApplicationInfo(packageName, 0); } catch (PackageManager.NameNotFoundException ignored) { 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; } return isSystemPackage(aInfo); } catch (PackageManager.NameNotFoundException e) { return false; } private static boolean isSystemPackage(@Nullable ApplicationInfo aInfo) { if (aInfo == null) { // 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 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) { if (sSystemSignature.equals(packageInfo.signatures[0])) { sSystemUids.put(uid, uid); return true; } // Platform signed packages are considered to be from the system if (aInfo.isSignedWithPlatformKey()) { return true; } finally { Binder.restoreCallingIdentity(identity); } return false; } } }