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

Commit adc69673 authored by Winson's avatar Winson Committed by Winson Chiu
Browse files

Add transient night mode in car mode when targeting Q

To support Android Auto, make UiModeManager.setNightMode transient when the device is in car mode. The manager will update the current visible night mode, but will not persist the setting. When exiting car mode, night mode is restored from the previous persisted setting.

If the user explicitly toggles night mode from settings, it will flip the visible mode and persisted setting, ignoring the transient behavior. This is handled in ag/6191550.

Bug: 117346726

Test: manual test app
Test: atest UiModeManagerTest CTS test in ag/6190842

Change-Id: I795f9b64a4d00bd3ecf47787e11aeb9331a64643
parent 49181399
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -229,7 +229,11 @@ public class UiModeManager {
     * <strong>Note:</strong> On API 22 and below, changes to the night mode
     * are only effective when the {@link Configuration#UI_MODE_TYPE_CAR car}
     * or {@link Configuration#UI_MODE_TYPE_DESK desk} mode is enabled on a
     * device. Starting in API 23, changes to night mode are always effective.
     * device. On API 23 through API 28, changes to night mode are always effective.
     * <p>
     * Starting in API 29, when the device is in car mode and this method is called, night mode
     * will change, but the new setting is not persisted and the previously persisted setting
     * will be restored when the device exits car mode.
     * <p>
     * Changes to night mode take effect globally and will result in a configuration change
     * (and potentially an Activity lifecycle event) being applied to all running apps.
+41 −3
Original line number Diff line number Diff line
@@ -30,11 +30,13 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.PowerManager;
import android.os.RemoteException;
@@ -340,8 +342,12 @@ final class UiModeManagerService extends SystemService {
            try {
                synchronized (mLock) {
                    if (mNightMode != mode) {
                        // Only persist setting if not transient night mode or not in car mode
                        if (!shouldTransientNightWhenInCarMode() || !mCarModeEnabled) {
                            Settings.Secure.putIntForUser(getContext().getContentResolver(),
                                    Settings.Secure.UI_NIGHT_MODE, mode, user);
                        }

                        mNightMode = mode;
                        updateLocked(0, 0);
                    }
@@ -424,9 +430,39 @@ final class UiModeManagerService extends SystemService {
        }
    }

    // Night mode settings in car mode are only persisted below Q.
    // When targeting Q, changes are not saved and night mode will be re-read
    // from settings when exiting car mode.
    private boolean shouldTransientNightWhenInCarMode() {
        int uid = Binder.getCallingUid();
        PackageManager packageManager = getContext().getPackageManager();
        String[] packagesForUid = packageManager.getPackagesForUid(uid);
        if (packagesForUid == null || packagesForUid.length == 0) {
            return false;
        }

        try {
            ApplicationInfo appInfo = packageManager.getApplicationInfoAsUser(
                    packagesForUid[0], 0, uid);

            return appInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
        } catch (PackageManager.NameNotFoundException ignored) {
        }

        return false;
    }

    void setCarModeLocked(boolean enabled, int flags) {
        if (mCarModeEnabled != enabled) {
            mCarModeEnabled = enabled;

            // When transient night mode and exiting car mode, restore night mode from settings
            if (shouldTransientNightWhenInCarMode() && !mCarModeEnabled) {
                Context context = getContext();
                updateNightModeFromSettings(context,
                        context.getResources(),
                        UserHandle.getCallingUserId());
            }
        }
        mCarModeEnableFlags = flags;
    }
@@ -484,7 +520,9 @@ final class UiModeManagerService extends SystemService {
            uiMode |= mNightMode << 4;
        }

        if (mPowerSave) {
        // Override night mode in power save mode if not transient night mode or not in car mode
        boolean shouldOverrideNight = !mCarModeEnabled || !shouldTransientNightWhenInCarMode();
        if (mPowerSave && shouldOverrideNight) {
            uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
            uiMode |= Configuration.UI_MODE_NIGHT_YES;
        }