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

Commit 3e605760 authored by Jay Aliomer's avatar Jay Aliomer
Browse files

DarkMode Tile affects all users + security bug

When setNightModeActivated is called, the change affects the current logged in user
Also, permission checks are made before changing dark theme
Test: manual
Bug: 168039904
Merged-In: I7786d9dde10f7547f5dd9fb00661fb89fde9f05c
Change-Id: I7786d9dde10f7547f5dd9fb00661fb89fde9f05c
(cherry picked from commit f16e87a9)
parent 01c000ef
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -510,6 +510,9 @@ public class UiModeManager {
    }

    /**
     * Activating night mode for the current user
     *
     * @return {@code true} if the change is successful
     * @hide
     */
    public boolean setNightModeActivated(boolean active) {
+3 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements
    private static final String PATTERN_HOUR_MINUTE = "h:mm a";
    private static final String PATTERN_HOUR_NINUTE_24 = "HH:mm";

    private final ColorDisplayManager mManager;
    private ColorDisplayManager mManager;
    private final LocationController mLocationController;
    private NightDisplayListener mListener;
    private boolean mIsListening;
@@ -105,6 +105,8 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements
            mListener.setCallback(null);
        }

        mManager = getHost().getUserContext().getSystemService(ColorDisplayManager.class);

        // Make a new controller for the new user.
        mListener = new NightDisplayListener(mContext, newUserId, new Handler(Looper.myLooper()));
        if (mIsListening) {
+2 −3
Original line number Diff line number Diff line
@@ -50,16 +50,15 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements
    public static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a");
    private final Icon mIcon = ResourceIcon.get(
            com.android.internal.R.drawable.ic_qs_ui_mode_night);
    private final UiModeManager mUiModeManager;
    private UiModeManager mUiModeManager;
    private final BatteryController mBatteryController;
    private final LocationController mLocationController;

    @Inject
    public UiModeNightTile(QSHost host, ConfigurationController configurationController,
            BatteryController batteryController, LocationController locationController) {
        super(host);
        mBatteryController = batteryController;
        mUiModeManager = mContext.getSystemService(UiModeManager.class);
        mUiModeManager = host.getUserContext().getSystemService(UiModeManager.class);
        mLocationController = locationController;
        configurationController.observe(getLifecycle(), this);
        batteryController.observe(getLifecycle(), this);
+20 −4
Original line number Diff line number Diff line
@@ -134,6 +134,7 @@ final class UiModeManagerService extends SystemService {
    int mCurUiMode = 0;
    private int mSetUiMode = 0;
    private boolean mHoldingConfiguration = false;
    private int mCurrentUser;

    private Configuration mConfiguration = new Configuration();
    boolean mSystemReady;
@@ -323,6 +324,7 @@ final class UiModeManagerService extends SystemService {
    @Override
    public void onSwitchUser(int userHandle) {
        super.onSwitchUser(userHandle);
      	mCurrentUser = userHandle;
        getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver);
        verifySetupWizardCompleted();
    }
@@ -728,16 +730,30 @@ final class UiModeManagerService extends SystemService {

        @Override
        public boolean setNightModeActivated(boolean active) {
            if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission(
                    android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
                    != PackageManager.PERMISSION_GRANTED)) {
                Slog.e(TAG, "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission");
                return false;
            }
            final int user = Binder.getCallingUserHandle().getIdentifier();
            if (user != mCurrentUser && getContext().checkCallingOrSelfPermission(
                    android.Manifest.permission.INTERACT_ACROSS_USERS)
                    != PackageManager.PERMISSION_GRANTED) {
                Slog.e(TAG, "Target user is not current user,"
                        + " INTERACT_ACROSS_USERS permission is required");
                return false;

            }
            synchronized (mLock) {
                final int user = UserHandle.getCallingUserId();
                final long ident = Binder.clearCallingIdentity();
                try {
                    if (mNightMode == MODE_NIGHT_AUTO || mNightMode == MODE_NIGHT_CUSTOM) {
                        unregisterScreenOffEventLocked();
                        mOverrideNightModeOff = !active;
                        mOverrideNightModeOn = active;
                        mOverrideNightModeUser = user;
                        persistNightModeOverrides(user);
                        mOverrideNightModeUser = mCurrentUser;
                        persistNightModeOverrides(mCurrentUser);
                    } else if (mNightMode == UiModeManager.MODE_NIGHT_NO
                            && active) {
                        mNightMode = UiModeManager.MODE_NIGHT_YES;
@@ -747,7 +763,7 @@ final class UiModeManagerService extends SystemService {
                    }
                    updateConfigurationLocked();
                    applyConfigurationExternallyLocked();
                    persistNightMode(user);
                    persistNightMode(mCurrentUser);
                    return true;
                } finally {
                    Binder.restoreCallingIdentity(ident);
+12 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server;

import android.Manifest;
import android.app.AlarmManager;
import android.app.IUiModeManager;
import android.content.BroadcastReceiver;
@@ -24,6 +25,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
@@ -66,6 +68,7 @@ import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -226,6 +229,15 @@ public class UiModeManagerServiceTest extends UiServiceTestCase {
        assertFalse(isNightModeActivated());
    }

    @Test
    public void setNightModeActivated_permissiontoChangeOtherUsers() throws RemoteException {
        mUiManagerService.onSwitchUser(9);
        when(mContext.checkCallingOrSelfPermission(
                eq(Manifest.permission.INTERACT_ACROSS_USERS)))
                .thenReturn(PackageManager.PERMISSION_DENIED);
        assertFalse(mService.setNightModeActivated(true));
    }

    @Test
    public void autoNightModeSwitch_batterySaverOn() throws RemoteException {
        mService.setNightMode(MODE_NIGHT_NO);