Loading services/core/java/com/android/server/pm/HsumBootUserInitializer.java +8 −2 Original line number Diff line number Diff line Loading @@ -70,9 +70,14 @@ public final class HsumBootUserInitializer { new ContentObserver(new Handler(Looper.getMainLooper())) { @Override public void onChange(boolean selfChange) { boolean isDeviceProvisioned = isDeviceProvisioned(); if (DEBUG) { Slogf.d(TAG, "onChange(%b): isDeviceProvisioned=%b", selfChange, isDeviceProvisioned); } // Set USER_SETUP_COMPLETE for the (headless) system user only when the device // has been set up at least once. if (isDeviceProvisioned()) { if (isDeviceProvisioned) { Slogf.i(TAG, "Marking USER_SETUP_COMPLETE for system user"); Settings.Secure.putInt(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1); Loading Loading @@ -352,7 +357,8 @@ public final class HsumBootUserInitializer { pw.println(res.getBoolean(R.bool.config_createInitialUser)); } private void observeDeviceProvisioning() { @VisibleForTesting void observeDeviceProvisioning() { if (isDeviceProvisioned()) { return; } Loading services/tests/mockingservicestests/src/com/android/server/pm/HsumBootUserInitializerTest.java +98 −0 Original line number Diff line number Diff line Loading @@ -15,11 +15,23 @@ */ package com.android.server.pm; import static android.provider.Settings.Global.DEVICE_PROVISIONED; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.os.UserManager; import android.provider.Settings; import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; Loading @@ -29,8 +41,11 @@ import com.android.server.am.ActivityManagerService; import com.google.common.truth.Expect; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; public final class HsumBootUserInitializerTest { Loading @@ -42,6 +57,8 @@ public final class HsumBootUserInitializerTest { @Rule public final ExtendedMockitoRule extendedMockito = new ExtendedMockitoRule.Builder(this) .mockStatic(UserManager.class) .spyStatic(Settings.Global.class) .spyStatic(Settings.Secure.class) .build(); @Mock private UserManagerService mMockUms; Loading @@ -51,11 +68,22 @@ public final class HsumBootUserInitializerTest { private PackageManagerService mMockPms; @Mock private ContentResolver mMockContentResolver; @Captor private ArgumentCaptor<ContentObserver> mCaptorContentObserver; // NOTE: not mocking yet, but need a real one because of resources private final Context mRealContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); private HsumBootUserInitializer mFixture; @Before public void setFixtures() { mFixture = new HsumBootUserInitializer(mMockUms, mMockAms, mMockPms, mMockContentResolver, // value of args below don't matter /* shouldDesignateMainUser= */ false, /* shouldCreateInitialUser= */ false); } @Test public void testCreateInstance_hsum() { mockIsHsum(true); Loading @@ -75,8 +103,78 @@ public final class HsumBootUserInitializerTest { expect.withMessage("result of createInstance()").that(instance).isNull(); } @Test public void testObserveDeviceProvisioning_provisioned() { mockIsDeviceProvisioned(true); mFixture.observeDeviceProvisioning(); verifyUserSetupCompleteNeverCalled(); verifyContentObserverNeverRegistered(); } @Test public void testObserveDeviceProvisioning_notProvisioned() { mockIsDeviceProvisioned(false); // First trigger setting an observer... mFixture.observeDeviceProvisioning(); verify(mMockContentResolver).registerContentObserver( eq(Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED)), eq(false), mCaptorContentObserver.capture()); var contentObserver = mCaptorContentObserver.getValue(); // ...then trigger the observer itself mockIsDeviceProvisioned(true); // onChange() expected it has changed contentObserver.onChange(true); verifyUserSetupCompleteCalled(); verifyContentObserverUnregistered(contentObserver); } private void mockIsHsum(boolean value) { Log.v(TAG, "mockIsHsum(" + value + ")"); doReturn(value).when(UserManager::isHeadlessSystemUserMode); } private void mockIsDeviceProvisioned(boolean value) { Log.v(TAG, "mockIsDeviceProvisioned(" + value + ")"); doReturn(value ? 1 : 0).when(() -> Settings.Global.getInt(any(), eq(DEVICE_PROVISIONED))); } private void verifyContentObserverUnregistered(ContentObserver contentObserver) { try { verify(mMockContentResolver).unregisterContentObserver(contentObserver); } catch (Throwable t) { Log.e(TAG, "verify failure:", t); expect.withMessage("ContentResolver (%s) was not unregistered", contentObserver).fail(); } } private void verifyContentObserverNeverRegistered() { try { verify(mMockContentResolver, never()).registerContentObserver(any(), anyBoolean(), any()); } catch (Throwable t) { Log.e(TAG, "verify failure:", t); expect.withMessage("should not have registered a content observer").fail(); } } private void verifyUserSetupCompleteCalled() { try { verify(() -> Settings.Secure.putInt(mMockContentResolver, USER_SETUP_COMPLETE, 1)); } catch (Throwable t) { Log.e(TAG, "verify failure:", t); expect.withMessage("USER_SETUP_COMPLETE was not set").fail(); } } private void verifyUserSetupCompleteNeverCalled() { try { verify(() -> Settings.Secure.putInt(any(), eq(USER_SETUP_COMPLETE), anyInt()), never()); } catch (Throwable t) { Log.e(TAG, "verify failure:", t); expect.withMessage("USER_SETUP_COMPLETE should not have been set").fail(); } } } Loading
services/core/java/com/android/server/pm/HsumBootUserInitializer.java +8 −2 Original line number Diff line number Diff line Loading @@ -70,9 +70,14 @@ public final class HsumBootUserInitializer { new ContentObserver(new Handler(Looper.getMainLooper())) { @Override public void onChange(boolean selfChange) { boolean isDeviceProvisioned = isDeviceProvisioned(); if (DEBUG) { Slogf.d(TAG, "onChange(%b): isDeviceProvisioned=%b", selfChange, isDeviceProvisioned); } // Set USER_SETUP_COMPLETE for the (headless) system user only when the device // has been set up at least once. if (isDeviceProvisioned()) { if (isDeviceProvisioned) { Slogf.i(TAG, "Marking USER_SETUP_COMPLETE for system user"); Settings.Secure.putInt(mContentResolver, Settings.Secure.USER_SETUP_COMPLETE, 1); Loading Loading @@ -352,7 +357,8 @@ public final class HsumBootUserInitializer { pw.println(res.getBoolean(R.bool.config_createInitialUser)); } private void observeDeviceProvisioning() { @VisibleForTesting void observeDeviceProvisioning() { if (isDeviceProvisioned()) { return; } Loading
services/tests/mockingservicestests/src/com/android/server/pm/HsumBootUserInitializerTest.java +98 −0 Original line number Diff line number Diff line Loading @@ -15,11 +15,23 @@ */ package com.android.server.pm; import static android.provider.Settings.Global.DEVICE_PROVISIONED; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.os.UserManager; import android.provider.Settings; import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; Loading @@ -29,8 +41,11 @@ import com.android.server.am.ActivityManagerService; import com.google.common.truth.Expect; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; public final class HsumBootUserInitializerTest { Loading @@ -42,6 +57,8 @@ public final class HsumBootUserInitializerTest { @Rule public final ExtendedMockitoRule extendedMockito = new ExtendedMockitoRule.Builder(this) .mockStatic(UserManager.class) .spyStatic(Settings.Global.class) .spyStatic(Settings.Secure.class) .build(); @Mock private UserManagerService mMockUms; Loading @@ -51,11 +68,22 @@ public final class HsumBootUserInitializerTest { private PackageManagerService mMockPms; @Mock private ContentResolver mMockContentResolver; @Captor private ArgumentCaptor<ContentObserver> mCaptorContentObserver; // NOTE: not mocking yet, but need a real one because of resources private final Context mRealContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); private HsumBootUserInitializer mFixture; @Before public void setFixtures() { mFixture = new HsumBootUserInitializer(mMockUms, mMockAms, mMockPms, mMockContentResolver, // value of args below don't matter /* shouldDesignateMainUser= */ false, /* shouldCreateInitialUser= */ false); } @Test public void testCreateInstance_hsum() { mockIsHsum(true); Loading @@ -75,8 +103,78 @@ public final class HsumBootUserInitializerTest { expect.withMessage("result of createInstance()").that(instance).isNull(); } @Test public void testObserveDeviceProvisioning_provisioned() { mockIsDeviceProvisioned(true); mFixture.observeDeviceProvisioning(); verifyUserSetupCompleteNeverCalled(); verifyContentObserverNeverRegistered(); } @Test public void testObserveDeviceProvisioning_notProvisioned() { mockIsDeviceProvisioned(false); // First trigger setting an observer... mFixture.observeDeviceProvisioning(); verify(mMockContentResolver).registerContentObserver( eq(Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED)), eq(false), mCaptorContentObserver.capture()); var contentObserver = mCaptorContentObserver.getValue(); // ...then trigger the observer itself mockIsDeviceProvisioned(true); // onChange() expected it has changed contentObserver.onChange(true); verifyUserSetupCompleteCalled(); verifyContentObserverUnregistered(contentObserver); } private void mockIsHsum(boolean value) { Log.v(TAG, "mockIsHsum(" + value + ")"); doReturn(value).when(UserManager::isHeadlessSystemUserMode); } private void mockIsDeviceProvisioned(boolean value) { Log.v(TAG, "mockIsDeviceProvisioned(" + value + ")"); doReturn(value ? 1 : 0).when(() -> Settings.Global.getInt(any(), eq(DEVICE_PROVISIONED))); } private void verifyContentObserverUnregistered(ContentObserver contentObserver) { try { verify(mMockContentResolver).unregisterContentObserver(contentObserver); } catch (Throwable t) { Log.e(TAG, "verify failure:", t); expect.withMessage("ContentResolver (%s) was not unregistered", contentObserver).fail(); } } private void verifyContentObserverNeverRegistered() { try { verify(mMockContentResolver, never()).registerContentObserver(any(), anyBoolean(), any()); } catch (Throwable t) { Log.e(TAG, "verify failure:", t); expect.withMessage("should not have registered a content observer").fail(); } } private void verifyUserSetupCompleteCalled() { try { verify(() -> Settings.Secure.putInt(mMockContentResolver, USER_SETUP_COMPLETE, 1)); } catch (Throwable t) { Log.e(TAG, "verify failure:", t); expect.withMessage("USER_SETUP_COMPLETE was not set").fail(); } } private void verifyUserSetupCompleteNeverCalled() { try { verify(() -> Settings.Secure.putInt(any(), eq(USER_SETUP_COMPLETE), anyInt()), never()); } catch (Throwable t) { Log.e(TAG, "verify failure:", t); expect.withMessage("USER_SETUP_COMPLETE should not have been set").fail(); } } }