Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +45 −1 Original line number Diff line number Diff line Loading @@ -395,6 +395,9 @@ public class SettingsProvider extends ContentProvider { private PackageMonitor mPackageMonitor; @GuardedBy("mLock") private VirtualDeviceManager.VirtualDeviceListener mVirtualDeviceListener; @GuardedBy("mLock") private boolean mSyncConfigDisabledUntilReboot; Loading Loading @@ -3192,9 +3195,50 @@ public class SettingsProvider extends ContentProvider { } private int getDeviceId() { return android.companion.virtualdevice.flags.Flags.deviceAwareSettingsOverride() int deviceId = android.companion.virtualdevice.flags.Flags.deviceAwareSettingsOverride() && canUidAccessDeviceAwareSettings(Binder.getCallingUid()) ? getCallingDeviceId() : Context.DEVICE_ID_DEFAULT; if (deviceId != Context.DEVICE_ID_DEFAULT) { // We have received a call for a non-default device id, so now would be a good time // to initialize a virtual device listener. initVirtualDeviceListener(); } return deviceId; } private void initVirtualDeviceListener() { synchronized (mLock) { // We already have a listener, just return. if (mVirtualDeviceListener != null) { return; } } VirtualDeviceManager virtualDeviceManager = getContext().getSystemService(VirtualDeviceManager.class); if (virtualDeviceManager == null) { return; } VirtualDeviceManager.VirtualDeviceListener listener; synchronized (mLock) { mVirtualDeviceListener = new VirtualDeviceManager.VirtualDeviceListener() { @Override public void onVirtualDeviceClosed(int deviceId) { // Clean up any device-specific settings when a virtual device is closed. List<UserInfo> userInfos = mUserManager.getAliveUsers(); for (UserInfo userInfo : userInfos) { synchronized (mLock) { mSettingsRegistry.removeUserAndDeviceStateLocked( userInfo.id, deviceId, true /* permanently */); } } } }; listener = mVirtualDeviceListener; } virtualDeviceManager.registerVirtualDeviceListener( mHandlerThread.getThreadExecutor(), listener); } private List<Integer> getDeviceIds() { Loading packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -315,7 +315,8 @@ abstract class BaseSettingsProviderTest { } } // Remove trailing line breaks from the output. return new String(result, StandardCharsets.UTF_8).replaceAll("\n", ""); String resultStr = new String(result, StandardCharsets.UTF_8).replaceAll("\n", ""); return "null".equals(resultStr) ? null : resultStr; } protected static void setSettingViaShell(int type, String name, String value, Loading packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java +68 −13 Original line number Diff line number Diff line Loading @@ -190,6 +190,42 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SYSTEM); } @Test @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_SETTINGS_OVERRIDE) public void testSystemSettingClearedOnVirtualDeviceRemovalForSystemUser() throws Exception { verifySettingsClearedOnVirtualDeviceRemoval(SETTING_TYPE_SYSTEM, UserHandle.USER_SYSTEM); } @Test @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_SETTINGS_OVERRIDE) public void testSecureSettingClearedOnVirtualDeviceRemovalForSystemUser() throws Exception { verifySettingsClearedOnVirtualDeviceRemoval(SETTING_TYPE_SECURE, UserHandle.USER_SYSTEM); } @Test @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_SETTINGS_OVERRIDE) public void testSystemSettingClearedOnVirtualDeviceRemovalForNonSystemUser() throws Exception { final int secondaryUserId = getSecondaryUserId(); if (secondaryUserId == UserHandle.USER_SYSTEM) { Log.w(LOG_TAG, "No secondary user. Skipping " + "testSystemSettingClearedOnVirtualDeviceRemovalForNonSystemUser"); return; } verifySettingsClearedOnVirtualDeviceRemoval(SETTING_TYPE_SYSTEM, secondaryUserId); } @Test @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_SETTINGS_OVERRIDE) public void testSecureSettingClearedOnVirtualDeviceRemovalForNonSystemUser() throws Exception { final int secondaryUserId = getSecondaryUserId(); if (secondaryUserId == UserHandle.USER_SYSTEM) { Log.w(LOG_TAG, "No secondary user. Skipping " + "testSecureSettingClearedOnVirtualDeviceRemovalForNonSystemUser"); return; } verifySettingsClearedOnVirtualDeviceRemoval(SETTING_TYPE_SECURE, secondaryUserId); } @Test public void testSelectAllGlobalViaProviderApi() throws Exception { setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_GLOBAL, Loading Loading @@ -674,19 +710,8 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { private void performSetAndGetSettingTestViaShell(int type, int userId, int deviceId) throws Exception { try { // Change the setting and assert a successful change. setSettingAndAssertSuccessfulChange( () -> { try { setSettingViaShell(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE, userId, deviceId); } catch (Exception e) { throw new RuntimeException(e); } }, BaseSettingsProviderTest::getSettingViaShell, type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE, userId, deviceId); setSettingViaShellAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE, userId, deviceId); } finally { // Remove the setting. setSettingViaShell(type, FAKE_SETTING_NAME, null /* value */, userId, deviceId); Loading Loading @@ -735,6 +760,22 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { } } private void verifySettingsClearedOnVirtualDeviceRemoval(int type, int userId) throws Exception { VirtualDeviceManager.VirtualDevice virtualDevice = mRule.createManagedVirtualDevice(); int deviceId = virtualDevice.getDeviceId(); // Change the setting and assert a successful change. setSettingViaShellAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE, userId, deviceId); virtualDevice.close(); // Wait for settings cleanup in SettingsProvider. SystemClock.sleep(2000L); String value = getSettingViaShell(type, FAKE_SETTING_NAME, userId, deviceId); assertNull(value); } private void setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, final String name, final String value, final int userId) { setSettingAndAssertSuccessfulChangeViaFrontEndApi(() -> Loading @@ -750,6 +791,20 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { name, value, getContext().getUserId()); } private void setSettingViaShellAndAssertSuccessfulChange(final int type, final String name, final String value, final int userId, final int deviceId) { setSettingAndAssertSuccessfulChange( () -> { try { setSettingViaShell(type, name, value, userId, deviceId); } catch (Exception e) { throw new RuntimeException(e); } }, BaseSettingsProviderTest::getSettingViaShell, type, name, value, userId, deviceId); } private void setSettingAndAssertSuccessfulChangeViaFrontEndApi(Runnable setCommand, final int type, final String name, final String value, final int userId) { setSettingAndAssertSuccessfulChange(setCommand, Loading Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +45 −1 Original line number Diff line number Diff line Loading @@ -395,6 +395,9 @@ public class SettingsProvider extends ContentProvider { private PackageMonitor mPackageMonitor; @GuardedBy("mLock") private VirtualDeviceManager.VirtualDeviceListener mVirtualDeviceListener; @GuardedBy("mLock") private boolean mSyncConfigDisabledUntilReboot; Loading Loading @@ -3192,9 +3195,50 @@ public class SettingsProvider extends ContentProvider { } private int getDeviceId() { return android.companion.virtualdevice.flags.Flags.deviceAwareSettingsOverride() int deviceId = android.companion.virtualdevice.flags.Flags.deviceAwareSettingsOverride() && canUidAccessDeviceAwareSettings(Binder.getCallingUid()) ? getCallingDeviceId() : Context.DEVICE_ID_DEFAULT; if (deviceId != Context.DEVICE_ID_DEFAULT) { // We have received a call for a non-default device id, so now would be a good time // to initialize a virtual device listener. initVirtualDeviceListener(); } return deviceId; } private void initVirtualDeviceListener() { synchronized (mLock) { // We already have a listener, just return. if (mVirtualDeviceListener != null) { return; } } VirtualDeviceManager virtualDeviceManager = getContext().getSystemService(VirtualDeviceManager.class); if (virtualDeviceManager == null) { return; } VirtualDeviceManager.VirtualDeviceListener listener; synchronized (mLock) { mVirtualDeviceListener = new VirtualDeviceManager.VirtualDeviceListener() { @Override public void onVirtualDeviceClosed(int deviceId) { // Clean up any device-specific settings when a virtual device is closed. List<UserInfo> userInfos = mUserManager.getAliveUsers(); for (UserInfo userInfo : userInfos) { synchronized (mLock) { mSettingsRegistry.removeUserAndDeviceStateLocked( userInfo.id, deviceId, true /* permanently */); } } } }; listener = mVirtualDeviceListener; } virtualDeviceManager.registerVirtualDeviceListener( mHandlerThread.getThreadExecutor(), listener); } private List<Integer> getDeviceIds() { Loading
packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -315,7 +315,8 @@ abstract class BaseSettingsProviderTest { } } // Remove trailing line breaks from the output. return new String(result, StandardCharsets.UTF_8).replaceAll("\n", ""); String resultStr = new String(result, StandardCharsets.UTF_8).replaceAll("\n", ""); return "null".equals(resultStr) ? null : resultStr; } protected static void setSettingViaShell(int type, String name, String value, Loading
packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderTest.java +68 −13 Original line number Diff line number Diff line Loading @@ -190,6 +190,42 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SYSTEM); } @Test @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_SETTINGS_OVERRIDE) public void testSystemSettingClearedOnVirtualDeviceRemovalForSystemUser() throws Exception { verifySettingsClearedOnVirtualDeviceRemoval(SETTING_TYPE_SYSTEM, UserHandle.USER_SYSTEM); } @Test @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_SETTINGS_OVERRIDE) public void testSecureSettingClearedOnVirtualDeviceRemovalForSystemUser() throws Exception { verifySettingsClearedOnVirtualDeviceRemoval(SETTING_TYPE_SECURE, UserHandle.USER_SYSTEM); } @Test @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_SETTINGS_OVERRIDE) public void testSystemSettingClearedOnVirtualDeviceRemovalForNonSystemUser() throws Exception { final int secondaryUserId = getSecondaryUserId(); if (secondaryUserId == UserHandle.USER_SYSTEM) { Log.w(LOG_TAG, "No secondary user. Skipping " + "testSystemSettingClearedOnVirtualDeviceRemovalForNonSystemUser"); return; } verifySettingsClearedOnVirtualDeviceRemoval(SETTING_TYPE_SYSTEM, secondaryUserId); } @Test @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_SETTINGS_OVERRIDE) public void testSecureSettingClearedOnVirtualDeviceRemovalForNonSystemUser() throws Exception { final int secondaryUserId = getSecondaryUserId(); if (secondaryUserId == UserHandle.USER_SYSTEM) { Log.w(LOG_TAG, "No secondary user. Skipping " + "testSecureSettingClearedOnVirtualDeviceRemovalForNonSystemUser"); return; } verifySettingsClearedOnVirtualDeviceRemoval(SETTING_TYPE_SECURE, secondaryUserId); } @Test public void testSelectAllGlobalViaProviderApi() throws Exception { setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_GLOBAL, Loading Loading @@ -674,19 +710,8 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { private void performSetAndGetSettingTestViaShell(int type, int userId, int deviceId) throws Exception { try { // Change the setting and assert a successful change. setSettingAndAssertSuccessfulChange( () -> { try { setSettingViaShell(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE, userId, deviceId); } catch (Exception e) { throw new RuntimeException(e); } }, BaseSettingsProviderTest::getSettingViaShell, type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE, userId, deviceId); setSettingViaShellAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE, userId, deviceId); } finally { // Remove the setting. setSettingViaShell(type, FAKE_SETTING_NAME, null /* value */, userId, deviceId); Loading Loading @@ -735,6 +760,22 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { } } private void verifySettingsClearedOnVirtualDeviceRemoval(int type, int userId) throws Exception { VirtualDeviceManager.VirtualDevice virtualDevice = mRule.createManagedVirtualDevice(); int deviceId = virtualDevice.getDeviceId(); // Change the setting and assert a successful change. setSettingViaShellAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE, userId, deviceId); virtualDevice.close(); // Wait for settings cleanup in SettingsProvider. SystemClock.sleep(2000L); String value = getSettingViaShell(type, FAKE_SETTING_NAME, userId, deviceId); assertNull(value); } private void setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, final String name, final String value, final int userId) { setSettingAndAssertSuccessfulChangeViaFrontEndApi(() -> Loading @@ -750,6 +791,20 @@ public class SettingsProviderTest extends BaseSettingsProviderTest { name, value, getContext().getUserId()); } private void setSettingViaShellAndAssertSuccessfulChange(final int type, final String name, final String value, final int userId, final int deviceId) { setSettingAndAssertSuccessfulChange( () -> { try { setSettingViaShell(type, name, value, userId, deviceId); } catch (Exception e) { throw new RuntimeException(e); } }, BaseSettingsProviderTest::getSettingViaShell, type, name, value, userId, deviceId); } private void setSettingAndAssertSuccessfulChangeViaFrontEndApi(Runnable setCommand, final int type, final String name, final String value, final int userId) { setSettingAndAssertSuccessfulChange(setCommand, Loading