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

Commit e5aeca3d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Cleanup TwilightService" into nyc-mr1-dev

parents e6c39fb5 6384878d
Loading
Loading
Loading
Loading
+0 −38
Original line number Diff line number Diff line
@@ -6172,44 +6172,6 @@ public final class Settings {
         */
        public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";

        /**
         * Behavior of twilight on the device.
         * One of {@link #TWILIGHT_MODE_LOCKED_OFF}, {@link #TWILIGHT_MODE_LOCKED_ON}
         * or {@link #TWILIGHT_MODE_AUTO}.
         * @hide
         */
        public static final String TWILIGHT_MODE = "twilight_mode";

        /**
         * Twilight mode always off.
         * @hide
         */
        public static final int TWILIGHT_MODE_LOCKED_OFF = 0;

        /**
         * Twilight mode always on.
         * @hide
         */
        public static final int TWILIGHT_MODE_LOCKED_ON = 1;

        /**
         * Twilight mode auto.
         * @hide
         */
        public static final int TWILIGHT_MODE_AUTO = 2;

        /**
         * Twilight mode auto, temporarily overriden to on.
         * @hide
         */
        public static final int TWILIGHT_MODE_AUTO_OVERRIDE_OFF = 3;

        /**
         * Twilight mode auto, temporarily overriden to off.
         * @hide
         */
        public static final int TWILIGHT_MODE_AUTO_OVERRIDE_ON = 4;

        /**
         * Whether brightness should automatically adjust based on twilight state.
         * @hide
+61 −170
Original line number Diff line number Diff line
@@ -16,18 +16,12 @@

package com.android.server.twilight;

import com.android.server.SystemService;
import com.android.server.TwilightCalculator;

import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
@@ -36,64 +30,52 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
import com.android.server.TwilightCalculator;

import java.util.ArrayList;
import java.util.Iterator;

import libcore.util.Objects;
import java.util.List;
import java.util.Objects;

/**
 * Figures out whether it's twilight time based on the user's location.
 *
 * <p>
 * Used by the UI mode manager and other components to adjust night mode
 * effects based on sunrise and sunset.
 */
public final class TwilightService extends SystemService {
    static final String TAG = "TwilightService";
    static final boolean DEBUG = false;
    static final String ACTION_UPDATE_TWILIGHT_STATE =
            "com.android.server.action.UPDATE_TWILIGHT_STATE";

    // The amount of time after or before sunrise over which to start adjusting
    // twilight affected things.  We want the change to happen gradually so that
    // it is below the threshold of perceptibility and so that the adjustment has
    // maximum effect well after dusk.
    private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;

    // Broadcast when twilight changes.
    public static final String ACTION_TWILIGHT_CHANGED = "android.intent.action.TWILIGHT_CHANGED";

    public static final String EXTRA_IS_NIGHT = "isNight";
    public static final String EXTRA_AMOUNT = "amount";

    // Amount of time the TwilightService will stay locked in an override state before switching
    // back to auto.
    private static final long RESET_TIME = DateUtils.HOUR_IN_MILLIS * 2;
    private static final String EXTRA_RESET_USER = "user";
    private static final String TAG = "TwilightService";
    private static final boolean DEBUG = false;

    private static final String ACTION_RESET_TWILIGHT_AUTO =
            "com.android.server.action.RESET_TWILIGHT_AUTO";
    private static final String ACTION_UPDATE_TWILIGHT_STATE =
            "com.android.server.action.UPDATE_TWILIGHT_STATE";

    final Object mLock = new Object();
    /**
     * The amount of time after or before sunrise over which to start adjusting twilight affected
     * things. We want the change to happen gradually so that it is below the threshold of
     * perceptibility and so that the adjustment has and so that the adjustment has
     * maximum effect well after dusk.
     */
    private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;

    AlarmManager mAlarmManager;
    LocationManager mLocationManager;
    LocationHandler mLocationHandler;
    private final Object mLock = new Object();

    final ArrayList<TwilightListenerRecord> mListeners =
            new ArrayList<TwilightListenerRecord>();
    @GuardedBy("mLock")
    private final List<TwilightListenerRecord> mListeners = new ArrayList<>();

    TwilightState mTwilightState;
    private AlarmManager mAlarmManager;
    private LocationManager mLocationManager;
    private LocationHandler mLocationHandler;

    private int mCurrentUser;
    private boolean mLocked;
    private boolean mBootCompleted;
    @GuardedBy("mLock")
    private TwilightState mTwilightState;

    public TwilightService(Context context) {
        super(context);
@@ -105,13 +87,11 @@ public final class TwilightService extends SystemService {
        mLocationManager = (LocationManager) getContext().getSystemService(
                Context.LOCATION_SERVICE);
        mLocationHandler = new LocationHandler();
        mCurrentUser = ActivityManager.getCurrentUser();

        IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        filter.addAction(Intent.ACTION_TIME_CHANGED);
        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
        filter.addAction(Intent.ACTION_USER_SWITCHED);
        filter.addAction(ACTION_UPDATE_TWILIGHT_STATE);
        getContext().registerReceiver(mReceiver, filter);

        publishLocalService(TwilightManager.class, mService);
@@ -120,81 +100,29 @@ public final class TwilightService extends SystemService {
    @Override
    public void onBootPhase(int phase) {
        if (phase == PHASE_BOOT_COMPLETED) {
            getContext().getContentResolver().registerContentObserver(
                    Secure.getUriFor(Secure.TWILIGHT_MODE), false, mContentObserver, mCurrentUser);
            mContentObserver.onChange(true);
            mBootCompleted = true;
            sendBroadcast();
        }
    }

    private void reregisterSettingObserver() {
        final ContentResolver contentResolver = getContext().getContentResolver();
        contentResolver.unregisterContentObserver(mContentObserver);
        contentResolver.registerContentObserver(Secure.getUriFor(Secure.TWILIGHT_MODE), false,
                mContentObserver, mCurrentUser);
        mContentObserver.onChange(true);
    }

    private void setLockedState(TwilightState state) {
        synchronized (mLock) {
            // Make sure we aren't locked so we can set the state.
            mLocked = false;
            setTwilightState(state);
            // Make sure we leave the state locked, so it cant be changed.
            mLocked = true;
            // TODO: Don't bother updating state when locked.
            // Initialize the current twilight state.
            mLocationHandler.requestTwilightUpdate();
        }
    }

    private void setTwilightState(TwilightState state) {
        synchronized (mLock) {
            if (mLocked) {
                // State has been locked by secure setting, shouldn't be changed.
                return;
            }
            if (!Objects.equal(mTwilightState, state)) {
            if (!Objects.equals(mTwilightState, state)) {
                if (DEBUG) {
                    Slog.d(TAG, "Twilight state changed: " + state);
                }

                mTwilightState = state;

                final int listenerLen = mListeners.size();
                for (int i = 0; i < listenerLen; i++) {
                    mListeners.get(i).postUpdate();
                for (TwilightListenerRecord mListener : mListeners) {
                    mListener.postUpdate();
                }
            }
        }
        sendBroadcast();
    }

    private void sendBroadcast() {
        synchronized (mLock) {
            if (mTwilightState == null) {
                return;
            }
            if (mBootCompleted) {
                Intent intent = new Intent(ACTION_TWILIGHT_CHANGED);
                intent.putExtra(EXTRA_IS_NIGHT, mTwilightState.isNight());
                intent.putExtra(EXTRA_AMOUNT, mTwilightState.getAmount());
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
            }
        }
    }

    private void scheduleReset() {
        long resetTime = System.currentTimeMillis() + RESET_TIME;
        Intent resetIntent = new Intent(ACTION_RESET_TWILIGHT_AUTO);
        resetIntent.putExtra(EXTRA_RESET_USER, mCurrentUser);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                getContext(), 0, resetIntent, 0);
        mAlarmManager.cancel(pendingIntent);
        mAlarmManager.setExact(AlarmManager.RTC, resetTime, pendingIntent);
    }

    private static class TwilightListenerRecord implements Runnable {

        private final TwilightListener mListener;
        private final Handler mHandler;

@@ -211,15 +139,9 @@ public final class TwilightService extends SystemService {
        public void run() {
            mListener.onTwilightStateChanged();
        }

    }

    private final TwilightManager mService = new TwilightManager() {
        /**
         * Gets the current twilight state.
         *
         * @return The current twilight state, or null if no information is available.
         */
        @Override
        public TwilightState getCurrentState() {
            synchronized (mLock) {
@@ -227,11 +149,6 @@ public final class TwilightService extends SystemService {
            }
        }

        /**
         * Listens for twilight time.
         *
         * @param listener The listener.
         */
        @Override
        public void registerListener(TwilightListener listener, Handler handler) {
            synchronized (mLock) {
@@ -286,6 +203,7 @@ public final class TwilightService extends SystemService {
    }

    private final class LocationHandler extends Handler {

        private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
        private static final int MSG_GET_NEW_LOCATION_UPDATE = 2;
        private static final int MSG_PROCESS_NEW_LOCATION = 3;
@@ -301,13 +219,14 @@ public final class TwilightService extends SystemService {
        private static final double FACTOR_GMT_OFFSET_LONGITUDE =
                1000.0 * 360.0 / DateUtils.DAY_IN_MILLIS;

        private final TwilightCalculator mTwilightCalculator = new TwilightCalculator();

        private boolean mPassiveListenerEnabled;
        private boolean mNetworkListenerEnabled;
        private boolean mDidFirstInit;
        private long mLastNetworkRegisterTime = -MIN_LOCATION_UPDATE_MS;
        private long mLastUpdateInterval;
        private Location mLocation;
        private final TwilightCalculator mTwilightCalculator = new TwilightCalculator();

        public void processNewLocation(Location location) {
            Message msg = obtainMessage(MSG_PROCESS_NEW_LOCATION, location);
@@ -373,8 +292,8 @@ public final class TwilightService extends SystemService {
                    // distance.
                    boolean networkLocationEnabled;
                    try {
                        networkLocationEnabled =
                            mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
                        networkLocationEnabled = mLocationManager.isProviderEnabled(
                                LocationManager.NETWORK_PROVIDER);
                    } catch (Exception e) {
                        // we may get IllegalArgumentException if network location provider
                        // does not exist or is not yet installed.
@@ -398,8 +317,8 @@ public final class TwilightService extends SystemService {
                    // and network).
                    boolean passiveLocationEnabled;
                    try {
                        passiveLocationEnabled =
                            mLocationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER);
                        passiveLocationEnabled = mLocationManager.isProviderEnabled(
                                LocationManager.PASSIVE_PROVIDER);
                    } catch (Exception e) {
                        // we may get IllegalArgumentException if passive location provider
                        // does not exist or is not yet installed.
@@ -450,8 +369,8 @@ public final class TwilightService extends SystemService {
            }

            // In the case there is no location available (e.g. GPS fix or network location
            // is not available yet), the longitude of the location is estimated using the timezone,
            // latitude and accuracy are set to get a good average.
            // is not available yet), the longitude of the location is estimated using the
            // timezone, latitude and accuracy are set to get a good average.
            if (location == null) {
                Time currentTime = new Time();
                currentTime.set(System.currentTimeMillis());
@@ -543,58 +462,22 @@ public final class TwilightService extends SystemService {
                Slog.d(TAG, "Next update in " + (nextUpdate - now) + " ms");
            }

            Intent updateIntent = new Intent(ACTION_UPDATE_TWILIGHT_STATE);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    getContext(), 0, updateIntent, 0);
            final PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    getContext(), 0, new Intent(ACTION_UPDATE_TWILIGHT_STATE), 0);
            mAlarmManager.cancel(pendingIntent);
            mAlarmManager.setExact(AlarmManager.RTC, nextUpdate, pendingIntent);
        }
    }

    private final ContentObserver mContentObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            int value = Secure.getIntForUser(getContext().getContentResolver(),
                    Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO, mCurrentUser);
            if (value == Secure.TWILIGHT_MODE_LOCKED_OFF) {
                setLockedState(new TwilightState(false, 0));
            } else if (value == Secure.TWILIGHT_MODE_LOCKED_ON) {
                setLockedState(new TwilightState(true, 1));
            } else if (value == Secure.TWILIGHT_MODE_AUTO_OVERRIDE_OFF) {
                setLockedState(new TwilightState(false, 0));
                scheduleReset();
            } else if (value == Secure.TWILIGHT_MODE_AUTO_OVERRIDE_ON) {
                setLockedState(new TwilightState(true, 1));
                scheduleReset();
            } else {
                mLocked = false;
                mLocationHandler.requestTwilightUpdate();
            }
        }
    };

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
                mCurrentUser = ActivityManager.getCurrentUser();
                reregisterSettingObserver();
                return;
            }
            if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())
                    && !intent.getBooleanExtra("state", false)) {
                // Airplane mode is now off!
                mLocationHandler.requestLocationUpdate();
                return;
            }

            if (ACTION_RESET_TWILIGHT_AUTO.equals(intent.getAction())) {
                int user = intent.getIntExtra(EXTRA_RESET_USER, 0);
                Settings.Secure.putIntForUser(getContext().getContentResolver(),
                        Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO, user);
                return;
            }
            // Time zone has changed or alarm expired.
            mLocationHandler.requestTwilightUpdate();
        }
@@ -603,31 +486,39 @@ public final class TwilightService extends SystemService {
    // A LocationListener to initialize the network location provider. The location updates
    // are handled through the passive location provider.
    private final LocationListener mEmptyLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
        }

        public void onProviderDisabled(String provider) {
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        @Override
        public void onProviderDisabled(String provider) {
        }
    };

    private final LocationListener mLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            mLocationHandler.processNewLocation(location);
        }

        public void onProviderDisabled(String provider) {
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        @Override
        public void onProviderDisabled(String provider) {
        }
    };
}
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import java.util.Date;
 * This object is immutable.
 */
public class TwilightState {

    private final boolean mIsNight;
    private final float mAmount;