Loading packages/SettingsProvider/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ android_library { "unsupportedappusage", ], static_libs: [ "aconfig_device_paths_java", "aconfig_new_storage_flags_lib", "aconfigd_java_utils", "aconfig_demo_flags_java_lib", Loading packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java +108 −14 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ import static android.provider.Settings.Config.SYNC_DISABLED_MODE_NONE; import static android.provider.Settings.Config.SYNC_DISABLED_MODE_PERSISTENT; import static android.provider.Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT; import android.aconfig.Aconfig.parsed_flag; import android.aconfig.Aconfig.parsed_flags; import android.aconfig.DeviceProtos; import android.aconfig.nano.Aconfig; import android.aconfig.nano.Aconfig.parsed_flag; import android.aconfig.nano.Aconfig.parsed_flags; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.content.AttributionSource; Loading @@ -42,7 +44,6 @@ import android.provider.Settings.Config.SyncDisabledMode; import android.provider.UpdatableDeviceConfigServiceReadiness; import android.util.Slog; import com.android.internal.pm.pkg.component.AconfigFlags; import com.android.internal.util.FastPrintWriter; import java.io.File; Loading Loading @@ -136,11 +137,8 @@ public final class DeviceConfigService extends Binder { continue; } for (parsed_flag flag : parsedFlags.getParsedFlagList()) { String namespace = flag.getNamespace(); String packageName = flag.getPackage(); String name = flag.getName(); nameSet.add(namespace + "/" + packageName + "." + name); for (parsed_flag flag : parsedFlags.parsedFlag) { nameSet.add(flag.namespace + "/" + flag.package_ + "." + flag.name); } } } catch (IOException e) { Loading Loading @@ -169,6 +167,7 @@ public final class DeviceConfigService extends Binder { static final class MyShellCommand extends ShellCommand { final SettingsProvider mProvider; private HashMap<String, parsed_flag> mAconfigParsedFlags; enum CommandVerb { GET, Loading @@ -186,6 +185,51 @@ public final class DeviceConfigService extends Binder { MyShellCommand(SettingsProvider provider) { mProvider = provider; if (Flags.checkRootAndReadOnly()) { List<parsed_flag> parsedFlags; try { parsedFlags = DeviceProtos.loadAndParseFlagProtos(); } catch (IOException e) { throw new IllegalStateException("failed to parse aconfig protos"); } mAconfigParsedFlags = new HashMap(); for (parsed_flag flag : parsedFlags) { mAconfigParsedFlags.put(flag.package_ + "." + flag.name, flag); } } } /** * Return true if a flag is aconfig. */ private boolean isAconfigFlag(String name) { return mAconfigParsedFlags.get(name) != null; } /** * Return true if a flag is both aconfig and read-only. * * @return true if a flag is both aconfig and read-only */ private boolean isReadOnly(String name) { parsed_flag flag = mAconfigParsedFlags.get(name); if (flag != null) { if (flag.permission == Aconfig.READ_ONLY) { return true; } } return false; } /** * Return true if the calling process is root. * * @return true if a flag is aconfig, and the calling process is root */ private boolean isRoot() { return Binder.getCallingUid() == Process.ROOT_UID; } public static HashMap<String, String> getAllFlags(IContentProvider provider) { Loading Loading @@ -414,21 +458,71 @@ public final class DeviceConfigService extends Binder { pout.println(DeviceConfig.getProperty(namespace, key)); break; case PUT: if (Flags.checkRootAndReadOnly()) { if (isAconfigFlag(key)) { if (!isRoot()) { pout.println("Error: must be root to write aconfig flag"); break; } if (isReadOnly(key)) { pout.println("Error: cannot write read-only flag"); break; } } } DeviceConfig.setProperty(namespace, key, value, makeDefault); break; case OVERRIDE: AconfigFlags.Permission permission = (new AconfigFlags()).getFlagPermission(key); if (permission == AconfigFlags.Permission.READ_ONLY) { pout.println("cannot override read-only flag " + key); } else { DeviceConfig.setLocalOverride(namespace, key, value); if (Flags.checkRootAndReadOnly()) { if (isAconfigFlag(key)) { if (!isRoot()) { pout.println("Error: must be root to write aconfig flag"); break; } if (isReadOnly(key)) { pout.println("Error: cannot write read-only flag"); break; } } } DeviceConfig.setLocalOverride(namespace, key, value); break; case CLEAR_OVERRIDE: if (Flags.checkRootAndReadOnly()) { if (isAconfigFlag(key)) { if (!isRoot()) { pout.println("Error: must be root to write aconfig flag"); break; } if (isReadOnly(key)) { pout.println("Error: cannot write read-only flag"); break; } } } DeviceConfig.clearLocalOverride(namespace, key); break; case DELETE: if (Flags.checkRootAndReadOnly()) { if (isAconfigFlag(key)) { if (!isRoot()) { pout.println("Error: must be root to write aconfig flag"); break; } if (isReadOnly(key)) { pout.println("Error: cannot write read-only flag"); break; } } } pout.println(delete(iprovider, namespace, key) ? "Successfully deleted " + key + " from " + namespace : "Failed to delete " + key + " from " + namespace); Loading packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -70,3 +70,14 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "check_root_and_read_only" namespace: "core_experiments_team_internal" description: "Check root and aconfig flag permissions in adb shell device_config commands." bug: "342636474" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } } Loading
packages/SettingsProvider/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ android_library { "unsupportedappusage", ], static_libs: [ "aconfig_device_paths_java", "aconfig_new_storage_flags_lib", "aconfigd_java_utils", "aconfig_demo_flags_java_lib", Loading
packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java +108 −14 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ import static android.provider.Settings.Config.SYNC_DISABLED_MODE_NONE; import static android.provider.Settings.Config.SYNC_DISABLED_MODE_PERSISTENT; import static android.provider.Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT; import android.aconfig.Aconfig.parsed_flag; import android.aconfig.Aconfig.parsed_flags; import android.aconfig.DeviceProtos; import android.aconfig.nano.Aconfig; import android.aconfig.nano.Aconfig.parsed_flag; import android.aconfig.nano.Aconfig.parsed_flags; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.content.AttributionSource; Loading @@ -42,7 +44,6 @@ import android.provider.Settings.Config.SyncDisabledMode; import android.provider.UpdatableDeviceConfigServiceReadiness; import android.util.Slog; import com.android.internal.pm.pkg.component.AconfigFlags; import com.android.internal.util.FastPrintWriter; import java.io.File; Loading Loading @@ -136,11 +137,8 @@ public final class DeviceConfigService extends Binder { continue; } for (parsed_flag flag : parsedFlags.getParsedFlagList()) { String namespace = flag.getNamespace(); String packageName = flag.getPackage(); String name = flag.getName(); nameSet.add(namespace + "/" + packageName + "." + name); for (parsed_flag flag : parsedFlags.parsedFlag) { nameSet.add(flag.namespace + "/" + flag.package_ + "." + flag.name); } } } catch (IOException e) { Loading Loading @@ -169,6 +167,7 @@ public final class DeviceConfigService extends Binder { static final class MyShellCommand extends ShellCommand { final SettingsProvider mProvider; private HashMap<String, parsed_flag> mAconfigParsedFlags; enum CommandVerb { GET, Loading @@ -186,6 +185,51 @@ public final class DeviceConfigService extends Binder { MyShellCommand(SettingsProvider provider) { mProvider = provider; if (Flags.checkRootAndReadOnly()) { List<parsed_flag> parsedFlags; try { parsedFlags = DeviceProtos.loadAndParseFlagProtos(); } catch (IOException e) { throw new IllegalStateException("failed to parse aconfig protos"); } mAconfigParsedFlags = new HashMap(); for (parsed_flag flag : parsedFlags) { mAconfigParsedFlags.put(flag.package_ + "." + flag.name, flag); } } } /** * Return true if a flag is aconfig. */ private boolean isAconfigFlag(String name) { return mAconfigParsedFlags.get(name) != null; } /** * Return true if a flag is both aconfig and read-only. * * @return true if a flag is both aconfig and read-only */ private boolean isReadOnly(String name) { parsed_flag flag = mAconfigParsedFlags.get(name); if (flag != null) { if (flag.permission == Aconfig.READ_ONLY) { return true; } } return false; } /** * Return true if the calling process is root. * * @return true if a flag is aconfig, and the calling process is root */ private boolean isRoot() { return Binder.getCallingUid() == Process.ROOT_UID; } public static HashMap<String, String> getAllFlags(IContentProvider provider) { Loading Loading @@ -414,21 +458,71 @@ public final class DeviceConfigService extends Binder { pout.println(DeviceConfig.getProperty(namespace, key)); break; case PUT: if (Flags.checkRootAndReadOnly()) { if (isAconfigFlag(key)) { if (!isRoot()) { pout.println("Error: must be root to write aconfig flag"); break; } if (isReadOnly(key)) { pout.println("Error: cannot write read-only flag"); break; } } } DeviceConfig.setProperty(namespace, key, value, makeDefault); break; case OVERRIDE: AconfigFlags.Permission permission = (new AconfigFlags()).getFlagPermission(key); if (permission == AconfigFlags.Permission.READ_ONLY) { pout.println("cannot override read-only flag " + key); } else { DeviceConfig.setLocalOverride(namespace, key, value); if (Flags.checkRootAndReadOnly()) { if (isAconfigFlag(key)) { if (!isRoot()) { pout.println("Error: must be root to write aconfig flag"); break; } if (isReadOnly(key)) { pout.println("Error: cannot write read-only flag"); break; } } } DeviceConfig.setLocalOverride(namespace, key, value); break; case CLEAR_OVERRIDE: if (Flags.checkRootAndReadOnly()) { if (isAconfigFlag(key)) { if (!isRoot()) { pout.println("Error: must be root to write aconfig flag"); break; } if (isReadOnly(key)) { pout.println("Error: cannot write read-only flag"); break; } } } DeviceConfig.clearLocalOverride(namespace, key); break; case DELETE: if (Flags.checkRootAndReadOnly()) { if (isAconfigFlag(key)) { if (!isRoot()) { pout.println("Error: must be root to write aconfig flag"); break; } if (isReadOnly(key)) { pout.println("Error: cannot write read-only flag"); break; } } } pout.println(delete(iprovider, namespace, key) ? "Successfully deleted " + key + " from " + namespace : "Failed to delete " + key + " from " + namespace); Loading
packages/SettingsProvider/src/com/android/providers/settings/device_config_service.aconfig +11 −0 Original line number Diff line number Diff line Loading @@ -70,3 +70,14 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "check_root_and_read_only" namespace: "core_experiments_team_internal" description: "Check root and aconfig flag permissions in adb shell device_config commands." bug: "342636474" is_fixed_read_only: true metadata { purpose: PURPOSE_BUGFIX } }