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

Commit 381e3300 authored by Jay Aliomer's avatar Jay Aliomer
Browse files

Dark theme twilight mode backend and tile

When the user has Dark theme scheduling turned on (b/141567787), the quick settings tile subtext should reflect the following:
If Dark theme is on: "Until sunrise"
If Dark theme is off: "On at sunset"
If the user does not have Dark theme scheduled, the text should not appear.
This matches the appearance of the Night Light QS tile.
All starting windows snapshots will be deleted and splash screens
will be used instead.

Test: atest UiModeManagerServiceTest
Fix: 143874807
Merged-In: Ie2ce64b5c5544fffe76be7ec3f971eb7461f8c4d

Change-Id: Ie2ce64b5c5544fffe76be7ec3f971eb7461f8c4d
(cherry picked from commit 8b2671b0)
parent 893a2b05
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -61,4 +61,9 @@ interface IUiModeManager {
     * Tells if Night mode is locked or not.
     */
    boolean isNightModeLocked();

    /**
    * @hide
    */
    boolean setNightModeActivated(boolean active);
}
+14 −0
Original line number Diff line number Diff line
@@ -317,4 +317,18 @@ public class UiModeManager {
        }
        return true;
    }

    /**
     * @hide*
     */
    public boolean setNightModeActivated(boolean active) {
        if (mService != null) {
            try {
                return mService.setNightModeActivated(active);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return false;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -894,6 +894,10 @@
    <string name="quick_settings_ui_mode_night_label">Dark theme</string>
    <!-- QuickSettings: Label for the dark theme tile when enabled by battery saver. [CHAR LIMIT=40] -->
    <string name="quick_settings_ui_mode_night_label_battery_saver">Dark theme\nBattery saver</string>
    <!-- QuickSettings: Secondary text for when the Dark Mode will be enabled at sunset. [CHAR LIMIT=20] -->
    <string name="quick_settings_dark_mode_secondary_label_on_at_sunset">On at sunset</string>
    <!-- QuickSettings: Secondary text for when the Dark Mode will be on until sunrise. [CHAR LIMIT=20] -->
    <string name="quick_settings_dark_mode_secondary_label_until_sunrise">Until sunrise</string>

    <!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] -->
    <string name="quick_settings_nfc_label">NFC</string>
+15 −6
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.widget.Switch;
import android.text.TextUtils;

import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.R;
@@ -79,24 +79,33 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements
            return;
        }
        boolean newState = !mState.value;
        mUiModeManager.setNightMode(newState ? UiModeManager.MODE_NIGHT_YES
                : UiModeManager.MODE_NIGHT_NO);
        mUiModeManager.setNightModeActivated(newState);
        refreshState(newState);
    }

    @Override
    protected void handleUpdateState(BooleanState state, Object arg) {
        int uiMode = mUiModeManager.getNightMode();
        boolean powerSave = mBatteryController.isPowerSave();
        boolean isAuto = uiMode == UiModeManager.MODE_NIGHT_AUTO;
        boolean nightMode = (mContext.getResources().getConfiguration().uiMode
                        & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;

        if (isAuto) {
            state.secondaryLabel = mContext.getResources().getString(nightMode
                    ? R.string.quick_settings_dark_mode_secondary_label_until_sunrise
                    : R.string.quick_settings_dark_mode_secondary_label_on_at_sunset);
        } else {
            state.secondaryLabel = null;
        }
        state.value = nightMode;
        state.label = mContext.getString(powerSave
                ? R.string.quick_settings_ui_mode_night_label_battery_saver
                : R.string.quick_settings_ui_mode_night_label);
        state.contentDescription = state.label;
        state.icon = mIcon;
        state.expandedAccessibilityClassName = Switch.class.getName();
        state.contentDescription = TextUtils.isEmpty(state.secondaryLabel)
                ? state.label
                : TextUtils.concat(state.label, ", ", state.secondaryLabel);
        if (powerSave) {
            state.state = Tile.STATE_UNAVAILABLE;
        } else {
+114 −6
Original line number Diff line number Diff line
@@ -53,8 +53,8 @@ import android.service.dreams.Sandman;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.DisableCarModeActivity;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
@@ -62,10 +62,13 @@ import com.android.internal.util.DumpUtils;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
import com.android.server.wm.WindowManagerInternal;

import java.io.FileDescriptor;
import java.io.PrintWriter;

import static android.content.Intent.ACTION_SCREEN_OFF;

final class UiModeManagerService extends SystemService {
    private static final String TAG = UiModeManager.class.getSimpleName();
    private static final boolean LOG = false;
@@ -79,6 +82,10 @@ final class UiModeManagerService extends SystemService {

    private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
    private int mNightMode = UiModeManager.MODE_NIGHT_NO;
    // we use the override auto mode
    // for example: force night mode off in the night time while in auto mode
    private int mNightModeOverride = mNightMode;
    protected static final String OVERRIDE_NIGHT_MODE = Secure.UI_NIGHT_MODE + "_override";

    private boolean mCarModeEnabled = false;
    private boolean mCharging = false;
@@ -112,6 +119,7 @@ final class UiModeManagerService extends SystemService {
    private TwilightManager mTwilightManager;
    private NotificationManager mNotificationManager;
    private StatusBarManager mStatusBarManager;
    private WindowManagerInternal mWindowManager;

    private PowerManager.WakeLock mWakeLock;

@@ -121,6 +129,17 @@ final class UiModeManagerService extends SystemService {
        super(context);
    }

    @VisibleForTesting
    protected UiModeManagerService(Context context, WindowManagerInternal wm,
                                   PowerManager.WakeLock wl, TwilightManager tm,
                                   boolean setupWizardComplete) {
        super(context);
        mWindowManager = wm;
        mWakeLock = wl;
        mTwilightManager = tm;
        mSetupWizardComplete = setupWizardComplete;
    }

    private static Intent buildHomeIntent(String category) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(category);
@@ -182,8 +201,23 @@ final class UiModeManagerService extends SystemService {
        public void onTwilightStateChanged(@Nullable TwilightState state) {
            synchronized (mLock) {
                if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
                    updateComputedNightModeLocked();
                    final IntentFilter intentFilter =
                            new IntentFilter(ACTION_SCREEN_OFF);
                    getContext().registerReceiver(mOnScreenOffHandler, intentFilter);
                }
            }
        }
    };

    private final BroadcastReceiver mOnScreenOffHandler = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            synchronized (mLock) {
                updateLocked(0, 0);
                try {
                    getContext().unregisterReceiver(mOnScreenOffHandler);
                } catch (IllegalArgumentException e) {
                    // we ignore this exception if the receiver is unregistered already.
                }
            }
        }
@@ -220,8 +254,10 @@ final class UiModeManagerService extends SystemService {
    private final ContentObserver mDarkThemeObserver = new ContentObserver(mHandler) {
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            final int mode = Secure.getIntForUser(getContext().getContentResolver(),
                    Secure.UI_NIGHT_MODE, mNightMode, 0);
            int mode = Secure.getIntForUser(getContext().getContentResolver(), Secure.UI_NIGHT_MODE,
                    mNightMode, 0);
            mode = mode == UiModeManager.MODE_NIGHT_AUTO
                    ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO;
            SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode));
        }
    };
@@ -240,6 +276,7 @@ final class UiModeManagerService extends SystemService {
        final PowerManager powerManager =
                (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
        mWindowManager = LocalServices.getService(WindowManagerInternal.class);

        // If setup isn't complete for this user listen for completion so we can unblock
        // being able to send a night mode configuration change event
@@ -306,6 +343,16 @@ final class UiModeManagerService extends SystemService {
                false, mDarkThemeObserver, 0);
    }

    @VisibleForTesting
    protected IUiModeManager getService() {
        return mService;
    }

    @VisibleForTesting
    protected Configuration getConfiguration() {
        return mConfiguration;
    }

    // Records whether setup wizard has happened or not and adds an observer for this user if not.
    private void verifySetupWizardCompleted() {
        final Context context = getContext();
@@ -340,8 +387,11 @@ final class UiModeManagerService extends SystemService {
        if (mSetupWizardComplete) {
            mNightMode = Secure.getIntForUser(context.getContentResolver(),
                    Secure.UI_NIGHT_MODE, defaultNightMode, userId);
            mNightModeOverride = Secure.getIntForUser(context.getContentResolver(),
                    OVERRIDE_NIGHT_MODE, defaultNightMode, userId);
        } else {
            mNightMode = defaultNightMode;
            mNightModeOverride = defaultNightMode;
        }

        return oldNightMode != mNightMode;
@@ -424,14 +474,30 @@ final class UiModeManagerService extends SystemService {
            try {
                synchronized (mLock) {
                    if (mNightMode != mode) {
                        if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
                            try {
                                getContext().unregisterReceiver(mOnScreenOffHandler);
                            } catch (IllegalArgumentException e) {
                                // we ignore this exception if the receiver is unregistered already.
                            }
                        }
                        // Only persist setting if not in car mode
                        if (!mCarModeEnabled) {
                            Secure.putIntForUser(getContext().getContentResolver(),
                                    Secure.UI_NIGHT_MODE, mode, user);
                            Secure.putIntForUser(getContext().getContentResolver(),
                                    OVERRIDE_NIGHT_MODE, mNightModeOverride, user);
                        }

                        mNightMode = mode;
                        mNightModeOverride = mode;
                        //on screen off will update configuration instead
                        if (mNightMode != UiModeManager.MODE_NIGHT_AUTO) {
                            updateLocked(0, 0);
                        } else {
                            getContext().registerReceiver(
                                    mOnScreenOffHandler, new IntentFilter(ACTION_SCREEN_OFF));
                        }
                    }
                }
            } finally {
@@ -471,6 +537,34 @@ final class UiModeManagerService extends SystemService {
            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
            dumpImpl(pw);
        }

        @Override
        public boolean setNightModeActivated(boolean active) {
            synchronized (mLock) {
                final long ident = Binder.clearCallingIdentity();
                try {
                    if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
                        try {
                            getContext().unregisterReceiver(mOnScreenOffHandler);
                        } catch (IllegalArgumentException e) {
                        }
                        mNightModeOverride = active
                                ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO;
                    } else if (mNightMode == UiModeManager.MODE_NIGHT_NO
                            && active) {
                        mNightMode = UiModeManager.MODE_NIGHT_YES;
                    } else if (mNightMode == UiModeManager.MODE_NIGHT_YES
                            && !active) {
                        mNightMode = UiModeManager.MODE_NIGHT_NO;
                    }
                    updateConfigurationLocked();
                    sendConfigurationLocked();
                    return true;
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }
        }
    };

    void dumpImpl(PrintWriter pw) {
@@ -848,6 +942,20 @@ final class UiModeManagerService extends SystemService {
            if (state != null) {
                mComputedNightMode = state.isNight();
            }
            if (mNightModeOverride == UiModeManager.MODE_NIGHT_YES && !mComputedNightMode) {
                mComputedNightMode = true;
                return;
            }
            if (mNightModeOverride == UiModeManager.MODE_NIGHT_NO && mComputedNightMode) {
                mComputedNightMode = false;
                return;
            }

            mNightModeOverride = mNightMode;
            final int user = UserHandle.getCallingUserId();
            Secure.putIntForUser(getContext().getContentResolver(),
                    OVERRIDE_NIGHT_MODE, mNightModeOverride, user);

        }
    }

Loading