Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d40fcddd authored by Chris Baron's avatar Chris Baron
Browse files

Allow enabling and disable car mode from the shell.

This got disabled inadvertently ag/16853283

Change-Id: I9e6b77f9cb6ed44eacbf87e17a77c99090d9488e
Bug: 232803470
parent c416376c
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -635,7 +635,12 @@ final class UiModeManagerService extends SystemService {
                        + "permission ENTER_CAR_MODE_PRIORITIZED");
            }

            // Allow the user to enable car mode using the shell,
            // e.g. 'adb shell cmd uimode car yes'
            boolean isShellCaller = mInjector.getCallingUid() == Process.SHELL_UID;
            if (!isShellCaller) {
              assertLegit(callingPackage);
            }

            final long ident = Binder.clearCallingIdentity();
            try {
@@ -676,8 +681,13 @@ final class UiModeManagerService extends SystemService {
            // If the caller is the system, we will allow the DISABLE_CAR_MODE_ALL_PRIORITIES car
            // mode flag to be specified; this is so that the user can disable car mode at all
            // priorities using the persistent notification.
            boolean isSystemCaller = mInjector.getCallingUid() == Process.SYSTEM_UID;
            if (!isSystemCaller) {
            //
            // We also allow the user to disable car mode using the shell,
            // e.g. 'adb shell cmd uimode car no'
            int callingUid = mInjector.getCallingUid();
            boolean isSystemCaller = callingUid == Process.SYSTEM_UID;
            boolean isShellCaller = callingUid == Process.SHELL_UID;
            if (!isSystemCaller && !isShellCaller) {
                assertLegit(callingPackage);
            }
            final int carModeFlags =
+68 −28
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
@@ -885,7 +886,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void requestProjection_failsForBogusPackageName() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID + 1);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID + 1);

        assertThrows(SecurityException.class, () -> mService.requestProjection(mBinder,
                PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME));
@@ -905,7 +906,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void requestProjection_failsIfNoProjectionTypes() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);

        assertThrows(IllegalArgumentException.class,
                () -> mService.requestProjection(mBinder, PROJECTION_TYPE_NONE, PACKAGE_NAME));
@@ -918,7 +919,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void requestProjection_failsIfMultipleProjectionTypes() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);

        // Don't use PROJECTION_TYPE_ALL because that's actually == -1 and will fail the > 0 check.
        int multipleProjectionTypes = PROJECTION_TYPE_AUTOMOTIVE | 0x0002 | 0x0004;
@@ -944,13 +945,13 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void requestProjection_automotive_failsIfAlreadySetByOtherPackage() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());

        String otherPackage = "Raconteurs";
        when(mPackageManager.getPackageUidAsUser(eq(otherPackage), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        assertFalse(mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, otherPackage));
        assertThat(mService.getProjectingPackages(PROJECTION_TYPE_AUTOMOTIVE),
                contains(PACKAGE_NAME));
@@ -959,7 +960,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void requestProjection_failsIfCannotLinkToDeath() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        doThrow(new RemoteException()).when(mBinder).linkToDeath(any(), anyInt());

        assertFalse(mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME));
@@ -969,7 +970,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void requestProjection() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        // Should work for all powers of two.
        for (int i = 0; i < Integer.SIZE; ++i) {
            int projectionType = 1 << i;
@@ -985,12 +986,12 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void releaseProjection_failsForBogusPackageName() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());

        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID + 1);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID + 1);

        assertThrows(SecurityException.class, () -> mService.releaseProjection(
                PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME));
@@ -1000,7 +1001,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void releaseProjection_failsIfNameNotFound() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
@@ -1014,7 +1015,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void releaseProjection_enforcesToggleAutomotiveProjectionPermission() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
        doThrow(new SecurityException()).when(mContext).enforceCallingPermission(
@@ -1033,7 +1034,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void releaseProjection() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        requestAllPossibleProjectionTypes();
        assertEquals(PROJECTION_TYPE_ALL, mService.getActiveProjectionTypes());

@@ -1053,7 +1054,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void binderDeath_releasesProjection() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        requestAllPossibleProjectionTypes();
        assertEquals(PROJECTION_TYPE_ALL, mService.getActiveProjectionTypes());
        ArgumentCaptor<IBinder.DeathRecipient> deathRecipientCaptor = ArgumentCaptor.forClass(
@@ -1069,7 +1070,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    public void getActiveProjectionTypes() throws Exception {
        assertEquals(PROJECTION_TYPE_NONE, mService.getActiveProjectionTypes());
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());
        mService.releaseProjection(PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
@@ -1080,7 +1081,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    public void getProjectingPackages() throws Exception {
        assertTrue(mService.getProjectingPackages(PROJECTION_TYPE_ALL).isEmpty());
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        assertEquals(1, mService.getProjectingPackages(PROJECTION_TYPE_AUTOMOTIVE).size());
        assertEquals(1, mService.getProjectingPackages(PROJECTION_TYPE_ALL).size());
@@ -1105,7 +1106,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    public void addOnProjectionStateChangedListener_callsListenerIfProjectionActive()
            throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        assertEquals(PROJECTION_TYPE_AUTOMOTIVE, mService.getActiveProjectionTypes());

@@ -1135,7 +1136,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
        mService.removeOnProjectionStateChangedListener(listener);
        // Now set automotive projection, should not call back.
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        verify(listener, never()).onProjectionStateChanged(anyInt(), any());
    }
@@ -1152,7 +1153,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {

        // Now set automotive projection, should call back.
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        verify(listener).onProjectionStateChanged(eq(PROJECTION_TYPE_AUTOMOTIVE),
                eq(List.of(PACKAGE_NAME)));
@@ -1179,9 +1180,9 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
        int otherFakeProjectionType = 0x0004;
        String otherPackageName = "Internet Arms";
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        when(mPackageManager.getPackageUidAsUser(eq(otherPackageName), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        IOnProjectionStateChangedListener listener = mock(IOnProjectionStateChangedListener.class);
        when(listener.asBinder()).thenReturn(mBinder); // Any binder will do.
        IOnProjectionStateChangedListener listener2 = mock(IOnProjectionStateChangedListener.class);
@@ -1234,7 +1235,7 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
        // Now kill the binder for the listener. This should remove it from the list of listeners.
        listenerDeathRecipient.getValue().binderDied();
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
                .thenReturn(TestInjector.CALLING_UID);
                .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.requestProjection(mBinder, PROJECTION_TYPE_AUTOMOTIVE, PACKAGE_NAME);
        verify(listener, never()).onProjectionStateChanged(anyInt(), any());
    }
@@ -1242,20 +1243,33 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    @Test
    public void enableCarMode_failsForBogusPackageName() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
            .thenReturn(TestInjector.CALLING_UID + 1);
            .thenReturn(TestInjector.DEFAULT_CALLING_UID + 1);

        assertThrows(SecurityException.class, () -> mService.enableCarMode(0, 0, PACKAGE_NAME));
        assertThat(mService.getCurrentModeType()).isNotEqualTo(Configuration.UI_MODE_TYPE_CAR);
    }

    @Test
    public void enableCarMode_shell() throws Exception {
        mUiManagerService = new UiModeManagerService(mContext, /* setupWizardComplete= */ true,
                mTwilightManager, new TestInjector(Process.SHELL_UID));
        try {
            mUiManagerService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
        } catch (SecurityException e) {/* ignore for permission denial */}
        mService = mUiManagerService.getService();

        mService.enableCarMode(0, 0, PACKAGE_NAME);
        assertThat(mService.getCurrentModeType()).isEqualTo(Configuration.UI_MODE_TYPE_CAR);
    }

    @Test
    public void disableCarMode_failsForBogusPackageName() throws Exception {
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
            .thenReturn(TestInjector.CALLING_UID);
            .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.enableCarMode(0, 0, PACKAGE_NAME);
        assertThat(mService.getCurrentModeType()).isEqualTo(Configuration.UI_MODE_TYPE_CAR);
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
            .thenReturn(TestInjector.CALLING_UID + 1);
            .thenReturn(TestInjector.DEFAULT_CALLING_UID + 1);

        assertThrows(SecurityException.class,
            () -> mService.disableCarModeByCallingPackage(0, PACKAGE_NAME));
@@ -1263,7 +1277,23 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {

        // Clean up
        when(mPackageManager.getPackageUidAsUser(eq(PACKAGE_NAME), anyInt()))
            .thenReturn(TestInjector.CALLING_UID);
            .thenReturn(TestInjector.DEFAULT_CALLING_UID);
        mService.disableCarModeByCallingPackage(0, PACKAGE_NAME);
        assertThat(mService.getCurrentModeType()).isNotEqualTo(Configuration.UI_MODE_TYPE_CAR);
    }

    @Test
    public void disableCarMode_shell() throws Exception {
        mUiManagerService = new UiModeManagerService(mContext, /* setupWizardComplete= */ true,
                mTwilightManager, new TestInjector(Process.SHELL_UID));
        try {
            mUiManagerService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
        } catch (SecurityException e) {/* ignore for permission denial */}
        mService = mUiManagerService.getService();

        mService.enableCarMode(0, 0, PACKAGE_NAME);
        assertThat(mService.getCurrentModeType()).isEqualTo(Configuration.UI_MODE_TYPE_CAR);

        mService.disableCarModeByCallingPackage(0, PACKAGE_NAME);
        assertThat(mService.getCurrentModeType()).isNotEqualTo(Configuration.UI_MODE_TYPE_CAR);
    }
@@ -1275,10 +1305,20 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
    }

    private static class TestInjector extends UiModeManagerService.Injector {
        private static final int CALLING_UID = 8675309;
        private static final int DEFAULT_CALLING_UID = 8675309;

        private final int callingUid;

        public TestInjector() {
          this(DEFAULT_CALLING_UID);
        }

        public TestInjector(int callingUid) {
          this.callingUid = callingUid;
        }

        public int getCallingUid() {
            return CALLING_UID;
            return callingUid;
        }
    }
}