/*
 * Copyright 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.display;

import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ParceledListSlice;
import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.RingBuffer;

import libcore.io.IoUtils;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.ArrayList;

import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Class that tracks recent brightness settings changes and stores
 * associated information such as light sensor readings.
 */
public class BrightnessTracker {

    static final String TAG = "BrightnessTracker";
    static final boolean DEBUG = false;

    private static final String EVENTS_FILE = "brightness_events.xml";
    private static final String AMBIENT_BRIGHTNESS_STATS_FILE = "ambient_brightness_stats.xml";
    private static final int MAX_EVENTS = 100;
    // Discard events when reading or writing that are older than this.
    private static final long MAX_EVENT_AGE = TimeUnit.DAYS.toMillis(30);
    // Time over which we keep lux sensor readings.
    private static final long LUX_EVENT_HORIZON = TimeUnit.SECONDS.toNanos(10);

    private static final String TAG_EVENTS = "events";
    private static final String TAG_EVENT = "event";
    private static final String ATTR_NITS = "nits";
    private static final String ATTR_TIMESTAMP = "timestamp";
    private static final String ATTR_PACKAGE_NAME = "packageName";
    private static final String ATTR_USER = "user";
    private static final String ATTR_LUX = "lux";
    private static final String ATTR_LUX_TIMESTAMPS = "luxTimestamps";
    private static final String ATTR_BATTERY_LEVEL = "batteryLevel";
    private static final String ATTR_NIGHT_MODE = "nightMode";
    private static final String ATTR_COLOR_TEMPERATURE = "colorTemperature";
    private static final String ATTR_LAST_NITS = "lastNits";
    private static final String ATTR_DEFAULT_CONFIG = "defaultConfig";
    private static final String ATTR_POWER_SAVE = "powerSaveFactor";
    private static final String ATTR_USER_POINT = "userPoint";

    private static final int MSG_BACKGROUND_START = 0;
    private static final int MSG_BRIGHTNESS_CHANGED = 1;
    private static final int MSG_STOP_SENSOR_LISTENER = 2;
    private static final int MSG_START_SENSOR_LISTENER = 3;

    // Lock held while accessing mEvents, is held while writing events to flash.
    private final Object mEventsLock = new Object();
    @GuardedBy("mEventsLock")
    private RingBuffer<BrightnessChangeEvent> mEvents
            = new RingBuffer<>(BrightnessChangeEvent.class, MAX_EVENTS);
    @GuardedBy("mEventsLock")
    private boolean mEventsDirty;

    private volatile boolean mWriteBrightnessTrackerStateScheduled;

    private AmbientBrightnessStatsTracker mAmbientBrightnessStatsTracker;

    private UserManager mUserManager;
    private final Context mContext;
    private final ContentResolver mContentResolver;
    private Handler mBgHandler;

    // mBroadcastReceiver,  mSensorListener, mSettingsObserver and mSensorRegistered
    // should only be used on the mBgHandler thread.
    private BroadcastReceiver mBroadcastReceiver;
    private SensorListener mSensorListener;
    private SettingsObserver mSettingsObserver;
    private boolean mSensorRegistered;

    private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;

    // Lock held while collecting data related to brightness changes.
    private final Object mDataCollectionLock = new Object();
    @GuardedBy("mDataCollectionLock")
    private Deque<LightData> mLastSensorReadings = new ArrayDeque<>();
    @GuardedBy("mDataCollectionLock")
    private float mLastBatteryLevel = Float.NaN;
    @GuardedBy("mDataCollectionLock")
    private float mLastBrightness = -1;
    @GuardedBy("mDataCollectionLock")
    private boolean mStarted;

    private final Injector mInjector;

    public BrightnessTracker(Context context, @Nullable Injector injector) {
        // Note this will be called very early in boot, other system
        // services may not be present.
        mContext = context;
        mContentResolver = context.getContentResolver();
        if (injector != null) {
            mInjector = injector;
        } else {
            mInjector = new Injector();
        }
    }

    /**
     * Start listening for brightness slider events
     *
     * @param initialBrightness the initial screen brightness
     */
    public void start(float initialBrightness) {
        if (DEBUG) {
            Slog.d(TAG, "Start");
        }
        mBgHandler = new TrackerHandler(mInjector.getBackgroundHandler().getLooper());
        mUserManager = mContext.getSystemService(UserManager.class);
        mCurrentUserId = ActivityManager.getCurrentUser();
        mBgHandler.obtainMessage(MSG_BACKGROUND_START, (Float) initialBrightness).sendToTarget();
    }

    private void backgroundStart(float initialBrightness) {
        readEvents();
        readAmbientBrightnessStats();

        mSensorListener = new SensorListener();

        mSettingsObserver = new SettingsObserver(mBgHandler);
        mInjector.registerBrightnessModeObserver(mContentResolver, mSettingsObserver);
        startSensorListener();

        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_SHUTDOWN);
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        mBroadcastReceiver = new Receiver();
        mInjector.registerReceiver(mContext, mBroadcastReceiver, intentFilter);

        mInjector.scheduleIdleJob(mContext);
        synchronized (mDataCollectionLock) {
            mLastBrightness = initialBrightness;
            mStarted = true;
        }
    }

    /** Stop listening for events */
    @VisibleForTesting
    void stop() {
        if (DEBUG) {
            Slog.d(TAG, "Stop");
        }
        mBgHandler.removeMessages(MSG_BACKGROUND_START);
        stopSensorListener();
        mInjector.unregisterSensorListener(mContext, mSensorListener);
        mInjector.unregisterBrightnessModeObserver(mContext, mSettingsObserver);
        mInjector.unregisterReceiver(mContext, mBroadcastReceiver);
        mInjector.cancelIdleJob(mContext);

        synchronized (mDataCollectionLock) {
            mStarted = false;
        }
    }

    public void onSwitchUser(@UserIdInt int newUserId) {
        if (DEBUG) {
            Slog.d(TAG, "Used id updated from " + mCurrentUserId + " to " + newUserId);
        }
        mCurrentUserId = newUserId;
    }

    /**
     * @param userId userId to fetch data for.
     * @param includePackage if false we will null out BrightnessChangeEvent.packageName
     * @return List of recent {@link BrightnessChangeEvent}s
     */
    public ParceledListSlice<BrightnessChangeEvent> getEvents(int userId, boolean includePackage) {
        BrightnessChangeEvent[] events;
        synchronized (mEventsLock) {
            events = mEvents.toArray();
        }
        int[] profiles = mInjector.getProfileIds(mUserManager, userId);
        Map<Integer, Boolean> toRedact = new HashMap<>();
        for (int i = 0; i < profiles.length; ++i) {
            int profileId = profiles[i];
            // Include slider interactions when a managed profile app is in the
            // foreground but always redact the package name.
            boolean redact = (!includePackage) || profileId != userId;
            toRedact.put(profiles[i], redact);
        }
        ArrayList<BrightnessChangeEvent> out = new ArrayList<>(events.length);
        for (int i = 0; i < events.length; ++i) {
            Boolean redact = toRedact.get(events[i].userId);
            if (redact != null) {
                if (!redact) {
                    out.add(events[i]);
                } else {
                    BrightnessChangeEvent event = new BrightnessChangeEvent((events[i]),
                            /* redactPackage */ true);
                    out.add(event);
                }
            }
        }
        return new ParceledListSlice<>(out);
    }

    public void persistBrightnessTrackerState() {
        scheduleWriteBrightnessTrackerState();
    }

    /**
     * Notify the BrightnessTracker that the user has changed the brightness of the display.
     */
    public void notifyBrightnessChanged(float brightness, boolean userInitiated,
            float powerBrightnessFactor, boolean isUserSetBrightness,
            boolean isDefaultBrightnessConfig) {
        if (DEBUG) {
            Slog.d(TAG, String.format("notifyBrightnessChanged(brightness=%f, userInitiated=%b)",
                        brightness, userInitiated));
        }
        Message m = mBgHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED,
                userInitiated ? 1 : 0, 0 /*unused*/, new BrightnessChangeValues(brightness,
                        powerBrightnessFactor, isUserSetBrightness, isDefaultBrightnessConfig));
        m.sendToTarget();
    }

    private void handleBrightnessChanged(float brightness, boolean userInitiated,
            float powerBrightnessFactor, boolean isUserSetBrightness,
            boolean isDefaultBrightnessConfig) {
        BrightnessChangeEvent.Builder builder;

        synchronized (mDataCollectionLock) {
            if (!mStarted) {
                // Not currently gathering brightness change information
                return;
            }

            float previousBrightness = mLastBrightness;
            mLastBrightness = brightness;

            if (!userInitiated) {
                // We want to record what current brightness is so that we know what the user
                // changed it from, but if it wasn't user initiated then we don't want to record it
                // as a BrightnessChangeEvent.
                return;
            }

            builder = new BrightnessChangeEvent.Builder();
            builder.setBrightness(brightness);
            builder.setTimeStamp(mInjector.currentTimeMillis());
            builder.setPowerBrightnessFactor(powerBrightnessFactor);
            builder.setUserBrightnessPoint(isUserSetBrightness);
            builder.setIsDefaultBrightnessConfig(isDefaultBrightnessConfig);

            final int readingCount = mLastSensorReadings.size();
            if (readingCount == 0) {
                // No sensor data so ignore this.
                return;
            }

            float[] luxValues = new float[readingCount];
            long[] luxTimestamps = new long[readingCount];

            int pos = 0;

            // Convert sensor timestamp in elapsed time nanos to current time millis.
            long currentTimeMillis = mInjector.currentTimeMillis();
            long elapsedTimeNanos = mInjector.elapsedRealtimeNanos();
            for (LightData reading : mLastSensorReadings) {
                luxValues[pos] = reading.lux;
                luxTimestamps[pos] = currentTimeMillis -
                        TimeUnit.NANOSECONDS.toMillis(elapsedTimeNanos - reading.timestamp);
                ++pos;
            }
            builder.setLuxValues(luxValues);
            builder.setLuxTimestamps(luxTimestamps);

            builder.setBatteryLevel(mLastBatteryLevel);
            builder.setLastBrightness(previousBrightness);
        }

        try {
            final ActivityManager.StackInfo focusedStack = mInjector.getFocusedStack();
            if (focusedStack != null && focusedStack.topActivity != null) {
                builder.setUserId(focusedStack.userId);
                builder.setPackageName(focusedStack.topActivity.getPackageName());
            } else {
                // Ignore the event because we can't determine user / package.
                if (DEBUG) {
                    Slog.d(TAG, "Ignoring event due to null focusedStack.");
                }
                return;
            }
        } catch (RemoteException e) {
            // Really shouldn't be possible.
            return;
        }

        builder.setNightMode(mInjector.getSecureIntForUser(mContentResolver,
                Settings.Secure.NIGHT_DISPLAY_ACTIVATED, 0, UserHandle.USER_CURRENT)
                == 1);
        builder.setColorTemperature(mInjector.getSecureIntForUser(mContentResolver,
                Settings.Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE,
                0, UserHandle.USER_CURRENT));

        BrightnessChangeEvent event = builder.build();
        if (DEBUG) {
            Slog.d(TAG, "Event " + event.brightness + " " + event.packageName);
        }
        synchronized (mEventsLock) {
            mEventsDirty = true;
            mEvents.append(event);
        }
    }

    private void startSensorListener() {
        if (!mSensorRegistered
                && mInjector.isInteractive(mContext)
                && mInjector.isBrightnessModeAutomatic(mContentResolver)) {
            mAmbientBrightnessStatsTracker.start();
            mSensorRegistered = true;
            mInjector.registerSensorListener(mContext, mSensorListener,
                    mInjector.getBackgroundHandler());
        }
    }

    private void stopSensorListener() {
        if (mSensorRegistered) {
            mAmbientBrightnessStatsTracker.stop();
            mInjector.unregisterSensorListener(mContext, mSensorListener);
            mSensorRegistered = false;
        }
    }

    private void scheduleWriteBrightnessTrackerState() {
        if (!mWriteBrightnessTrackerStateScheduled) {
            mBgHandler.post(() -> {
                mWriteBrightnessTrackerStateScheduled = false;
                writeEvents();
                writeAmbientBrightnessStats();
            });
            mWriteBrightnessTrackerStateScheduled = true;
        }
    }

    private void writeEvents() {
        synchronized (mEventsLock) {
            if (!mEventsDirty) {
                // Nothing to write
                return;
            }

            final AtomicFile writeTo = mInjector.getFile(EVENTS_FILE);
            if (writeTo == null) {
                return;
            }
            if (mEvents.isEmpty()) {
                if (writeTo.exists()) {
                    writeTo.delete();
                }
                mEventsDirty = false;
            } else {
                FileOutputStream output = null;
                try {
                    output = writeTo.startWrite();
                    writeEventsLocked(output);
                    writeTo.finishWrite(output);
                    mEventsDirty = false;
                } catch (IOException e) {
                    writeTo.failWrite(output);
                    Slog.e(TAG, "Failed to write change mEvents.", e);
                }
            }
        }
    }

    private void writeAmbientBrightnessStats() {
        final AtomicFile writeTo = mInjector.getFile(AMBIENT_BRIGHTNESS_STATS_FILE);
        if (writeTo == null) {
            return;
        }
        FileOutputStream output = null;
        try {
            output = writeTo.startWrite();
            mAmbientBrightnessStatsTracker.writeStats(output);
            writeTo.finishWrite(output);
        } catch (IOException e) {
            writeTo.failWrite(output);
            Slog.e(TAG, "Failed to write ambient brightness stats.", e);
        }
    }

    private void readEvents() {
        synchronized (mEventsLock) {
            // Read might prune events so mark as dirty.
            mEventsDirty = true;
            mEvents.clear();
            final AtomicFile readFrom = mInjector.getFile(EVENTS_FILE);
            if (readFrom != null && readFrom.exists()) {
                FileInputStream input = null;
                try {
                    input = readFrom.openRead();
                    readEventsLocked(input);
                } catch (IOException e) {
                    readFrom.delete();
                    Slog.e(TAG, "Failed to read change mEvents.", e);
                } finally {
                    IoUtils.closeQuietly(input);
                }
            }
        }
    }

    private void readAmbientBrightnessStats() {
        mAmbientBrightnessStatsTracker = new AmbientBrightnessStatsTracker(mUserManager, null);
        final AtomicFile readFrom = mInjector.getFile(AMBIENT_BRIGHTNESS_STATS_FILE);
        if (readFrom != null && readFrom.exists()) {
            FileInputStream input = null;
            try {
                input = readFrom.openRead();
                mAmbientBrightnessStatsTracker.readStats(input);
            } catch (IOException e) {
                readFrom.delete();
                Slog.e(TAG, "Failed to read ambient brightness stats.", e);
            } finally {
                IoUtils.closeQuietly(input);
            }
        }
    }

    @VisibleForTesting
    @GuardedBy("mEventsLock")
    void writeEventsLocked(OutputStream stream) throws IOException {
        XmlSerializer out = new FastXmlSerializer();
        out.setOutput(stream, StandardCharsets.UTF_8.name());
        out.startDocument(null, true);
        out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);

        out.startTag(null, TAG_EVENTS);
        BrightnessChangeEvent[] toWrite = mEvents.toArray();
        // Clear events, code below will add back the ones that are still within the time window.
        mEvents.clear();
        if (DEBUG) {
            Slog.d(TAG, "Writing events " + toWrite.length);
        }
        final long timeCutOff = mInjector.currentTimeMillis() - MAX_EVENT_AGE;
        for (int i = 0; i < toWrite.length; ++i) {
            int userSerialNo = mInjector.getUserSerialNumber(mUserManager, toWrite[i].userId);
            if (userSerialNo != -1 && toWrite[i].timeStamp > timeCutOff) {
                mEvents.append(toWrite[i]);
                out.startTag(null, TAG_EVENT);
                out.attribute(null, ATTR_NITS, Float.toString(toWrite[i].brightness));
                out.attribute(null, ATTR_TIMESTAMP, Long.toString(toWrite[i].timeStamp));
                out.attribute(null, ATTR_PACKAGE_NAME, toWrite[i].packageName);
                out.attribute(null, ATTR_USER, Integer.toString(userSerialNo));
                out.attribute(null, ATTR_BATTERY_LEVEL, Float.toString(toWrite[i].batteryLevel));
                out.attribute(null, ATTR_NIGHT_MODE, Boolean.toString(toWrite[i].nightMode));
                out.attribute(null, ATTR_COLOR_TEMPERATURE, Integer.toString(
                        toWrite[i].colorTemperature));
                out.attribute(null, ATTR_LAST_NITS,
                        Float.toString(toWrite[i].lastBrightness));
                out.attribute(null, ATTR_DEFAULT_CONFIG,
                        Boolean.toString(toWrite[i].isDefaultBrightnessConfig));
                out.attribute(null, ATTR_POWER_SAVE,
                        Float.toString(toWrite[i].powerBrightnessFactor));
                out.attribute(null, ATTR_USER_POINT,
                        Boolean.toString(toWrite[i].isUserSetBrightness));
                StringBuilder luxValues = new StringBuilder();
                StringBuilder luxTimestamps = new StringBuilder();
                for (int j = 0; j < toWrite[i].luxValues.length; ++j) {
                    if (j > 0) {
                        luxValues.append(',');
                        luxTimestamps.append(',');
                    }
                    luxValues.append(Float.toString(toWrite[i].luxValues[j]));
                    luxTimestamps.append(Long.toString(toWrite[i].luxTimestamps[j]));
                }
                out.attribute(null, ATTR_LUX, luxValues.toString());
                out.attribute(null, ATTR_LUX_TIMESTAMPS, luxTimestamps.toString());
                out.endTag(null, TAG_EVENT);
            }
        }
        out.endTag(null, TAG_EVENTS);
        out.endDocument();
        stream.flush();
    }

    @VisibleForTesting
    @GuardedBy("mEventsLock")
    void readEventsLocked(InputStream stream) throws IOException {
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(stream, StandardCharsets.UTF_8.name());

            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && type != XmlPullParser.START_TAG) {
            }
            String tag = parser.getName();
            if (!TAG_EVENTS.equals(tag)) {
                throw new XmlPullParserException(
                        "Events not found in brightness tracker file " + tag);
            }

            final long timeCutOff = mInjector.currentTimeMillis() - MAX_EVENT_AGE;

            parser.next();
            int outerDepth = parser.getDepth();
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                    continue;
                }
                tag = parser.getName();
                if (TAG_EVENT.equals(tag)) {
                    BrightnessChangeEvent.Builder builder = new BrightnessChangeEvent.Builder();

                    String brightness = parser.getAttributeValue(null, ATTR_NITS);
                    builder.setBrightness(Float.parseFloat(brightness));
                    String timestamp = parser.getAttributeValue(null, ATTR_TIMESTAMP);
                    builder.setTimeStamp(Long.parseLong(timestamp));
                    builder.setPackageName(parser.getAttributeValue(null, ATTR_PACKAGE_NAME));
                    String user = parser.getAttributeValue(null, ATTR_USER);
                    builder.setUserId(mInjector.getUserId(mUserManager, Integer.parseInt(user)));
                    String batteryLevel = parser.getAttributeValue(null, ATTR_BATTERY_LEVEL);
                    builder.setBatteryLevel(Float.parseFloat(batteryLevel));
                    String nightMode = parser.getAttributeValue(null, ATTR_NIGHT_MODE);
                    builder.setNightMode(Boolean.parseBoolean(nightMode));
                    String colorTemperature =
                            parser.getAttributeValue(null, ATTR_COLOR_TEMPERATURE);
                    builder.setColorTemperature(Integer.parseInt(colorTemperature));
                    String lastBrightness = parser.getAttributeValue(null, ATTR_LAST_NITS);
                    builder.setLastBrightness(Float.parseFloat(lastBrightness));

                    String luxValue = parser.getAttributeValue(null, ATTR_LUX);
                    String luxTimestamp = parser.getAttributeValue(null, ATTR_LUX_TIMESTAMPS);

                    String[] luxValuesStrings = luxValue.split(",");
                    String[] luxTimestampsStrings = luxTimestamp.split(",");
                    if (luxValuesStrings.length != luxTimestampsStrings.length) {
                        continue;
                    }
                    float[] luxValues = new float[luxValuesStrings.length];
                    long[] luxTimestamps = new long[luxValuesStrings.length];
                    for (int i = 0; i < luxValues.length; ++i) {
                        luxValues[i] = Float.parseFloat(luxValuesStrings[i]);
                        luxTimestamps[i] = Long.parseLong(luxTimestampsStrings[i]);
                    }
                    builder.setLuxValues(luxValues);
                    builder.setLuxTimestamps(luxTimestamps);

                    String defaultConfig = parser.getAttributeValue(null, ATTR_DEFAULT_CONFIG);
                    if (defaultConfig != null) {
                        builder.setIsDefaultBrightnessConfig(Boolean.parseBoolean(defaultConfig));
                    }
                    String powerSave = parser.getAttributeValue(null, ATTR_POWER_SAVE);
                    if (powerSave != null) {
                        builder.setPowerBrightnessFactor(Float.parseFloat(powerSave));
                    } else {
                        builder.setPowerBrightnessFactor(1.0f);
                    }
                    String userPoint = parser.getAttributeValue(null, ATTR_USER_POINT);
                    if (userPoint != null) {
                        builder.setUserBrightnessPoint(Boolean.parseBoolean(userPoint));
                    }

                    BrightnessChangeEvent event = builder.build();
                    if (DEBUG) {
                        Slog.i(TAG, "Read event " + event.brightness
                                + " " + event.packageName);
                    }

                    if (event.userId != -1 && event.timeStamp > timeCutOff
                            && event.luxValues.length > 0) {
                        mEvents.append(event);
                    }
                }
            }
        } catch (NullPointerException | NumberFormatException | XmlPullParserException
                | IOException e) {
            // Failed to parse something, just start with an empty event log.
            mEvents = new RingBuffer<>(BrightnessChangeEvent.class, MAX_EVENTS);
            Slog.e(TAG, "Failed to parse brightness event", e);
            // Re-throw so we will delete the bad file.
            throw new IOException("failed to parse file", e);
        }
    }

    public void dump(PrintWriter pw) {
        pw.println("BrightnessTracker state:");
        synchronized (mDataCollectionLock) {
            pw.println("  mStarted=" + mStarted);
            pw.println("  mLastSensorReadings.size=" + mLastSensorReadings.size());
            if (!mLastSensorReadings.isEmpty()) {
                pw.println("  mLastSensorReadings time span "
                        + mLastSensorReadings.peekFirst().timestamp + "->"
                        + mLastSensorReadings.peekLast().timestamp);
            }
        }
        synchronized (mEventsLock) {
            pw.println("  mEventsDirty=" + mEventsDirty);
            pw.println("  mEvents.size=" + mEvents.size());
            BrightnessChangeEvent[] events = mEvents.toArray();
            for (int i = 0; i < events.length; ++i) {
                pw.print("    " + events[i].timeStamp + ", " + events[i].userId);
                pw.print(", " + events[i].lastBrightness + "->" + events[i].brightness);
                pw.print(", isUserSetBrightness=" + events[i].isUserSetBrightness);
                pw.print(", powerBrightnessFactor=" + events[i].powerBrightnessFactor);
                pw.print(", isDefaultBrightnessConfig=" + events[i].isDefaultBrightnessConfig);
                pw.print(" {");
                for (int j = 0; j < events[i].luxValues.length; ++j){
                    if (j != 0) {
                        pw.print(", ");
                    }
                    pw.print("(" + events[i].luxValues[j] + "," + events[i].luxTimestamps[j] + ")");
                }
                pw.println("}");
            }
        }
        if (mAmbientBrightnessStatsTracker != null) {
            pw.println();
            mAmbientBrightnessStatsTracker.dump(pw);
        }
    }

    public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(int userId) {
        if (mAmbientBrightnessStatsTracker != null) {
            ArrayList<AmbientBrightnessDayStats> stats =
                    mAmbientBrightnessStatsTracker.getUserStats(
                            userId);
            if (stats != null) {
                return new ParceledListSlice<>(stats);
            }
        }
        return ParceledListSlice.emptyList();
    }

    // Not allowed to keep the SensorEvent so used to copy the data we care about.
    private static class LightData {
        public float lux;
        // Time in elapsedRealtimeNanos
        public long timestamp;
    }

    private void recordSensorEvent(SensorEvent event) {
        long horizon = mInjector.elapsedRealtimeNanos() - LUX_EVENT_HORIZON;
        synchronized (mDataCollectionLock) {
            if (DEBUG) {
                Slog.v(TAG, "Sensor event " + event);
            }
            if (!mLastSensorReadings.isEmpty()
                    && event.timestamp < mLastSensorReadings.getLast().timestamp) {
                // Ignore event that came out of order.
                return;
            }
            LightData data = null;
            while (!mLastSensorReadings.isEmpty()
                    && mLastSensorReadings.getFirst().timestamp < horizon) {
                // Remove data that has fallen out of the window.
                data = mLastSensorReadings.removeFirst();
            }
            // We put back the last one we removed so we know how long
            // the first sensor reading was valid for.
            if (data != null) {
                mLastSensorReadings.addFirst(data);
            }

            data = new LightData();
            data.timestamp = event.timestamp;
            data.lux = event.values[0];
            mLastSensorReadings.addLast(data);
        }
    }

    private void recordAmbientBrightnessStats(SensorEvent event) {
        mAmbientBrightnessStatsTracker.add(mCurrentUserId, event.values[0]);
    }

    private void batteryLevelChanged(int level, int scale) {
        synchronized (mDataCollectionLock) {
            mLastBatteryLevel = (float) level / (float) scale;
        }
    }

    private final class SensorListener implements SensorEventListener {
        @Override
        public void onSensorChanged(SensorEvent event) {
            recordSensorEvent(event);
            recordAmbientBrightnessStats(event);
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    }

    private final class SettingsObserver extends ContentObserver {
        public SettingsObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (DEBUG) {
                Slog.v(TAG, "settings change " + uri);
            }
            if (mInjector.isBrightnessModeAutomatic(mContentResolver)) {
                mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget();
            } else {
                mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget();
            }
        }
    }

    private final class Receiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DEBUG) {
                Slog.d(TAG, "Received " + intent.getAction());
            }
            String action = intent.getAction();
            if (Intent.ACTION_SHUTDOWN.equals(action)) {
                stop();
                scheduleWriteBrightnessTrackerState();
            } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
                int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
                int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
                if (level != -1 && scale != 0) {
                    batteryLevelChanged(level, scale);
                }
            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget();
            } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
                mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget();
            }
        }
    }

    private final class TrackerHandler extends Handler {
        public TrackerHandler(Looper looper) {
            super(looper, null, true /*async*/);
        }
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_BACKGROUND_START:
                    backgroundStart((float)msg.obj /*initial brightness*/);
                    break;
                case MSG_BRIGHTNESS_CHANGED:
                    BrightnessChangeValues values = (BrightnessChangeValues) msg.obj;
                    boolean userInitiatedChange = (msg.arg1 == 1);
                    handleBrightnessChanged(values.brightness, userInitiatedChange,
                            values.powerBrightnessFactor, values.isUserSetBrightness,
                            values.isDefaultBrightnessConfig);
                    break;
                case MSG_START_SENSOR_LISTENER:
                    startSensorListener();
                    break;
                case MSG_STOP_SENSOR_LISTENER:
                    stopSensorListener();
                    break;
            }
        }
    }

    private static class BrightnessChangeValues {
        final float brightness;
        final float powerBrightnessFactor;
        final boolean isUserSetBrightness;
        final boolean isDefaultBrightnessConfig;

        BrightnessChangeValues(float brightness, float powerBrightnessFactor,
                boolean isUserSetBrightness, boolean isDefaultBrightnessConfig) {
            this.brightness = brightness;
            this.powerBrightnessFactor = powerBrightnessFactor;
            this.isUserSetBrightness = isUserSetBrightness;
            this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
        }
    }

    @VisibleForTesting
    static class Injector {
        public void registerSensorListener(Context context,
                SensorEventListener sensorListener, Handler handler) {
            SensorManager sensorManager = context.getSystemService(SensorManager.class);
            Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
            sensorManager.registerListener(sensorListener,
                    lightSensor, SensorManager.SENSOR_DELAY_NORMAL, handler);
        }

        public void unregisterSensorListener(Context context, SensorEventListener sensorListener) {
            SensorManager sensorManager = context.getSystemService(SensorManager.class);
            sensorManager.unregisterListener(sensorListener);
        }

        public void registerBrightnessModeObserver(ContentResolver resolver,
                ContentObserver settingsObserver) {
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.SCREEN_BRIGHTNESS_MODE),
                    false, settingsObserver, UserHandle.USER_ALL);
        }

        public void unregisterBrightnessModeObserver(Context context,
                ContentObserver settingsObserver) {
            context.getContentResolver().unregisterContentObserver(settingsObserver);
        }

        public void registerReceiver(Context context,
                BroadcastReceiver receiver, IntentFilter filter) {
            context.registerReceiver(receiver, filter);
        }

        public void unregisterReceiver(Context context,
                BroadcastReceiver receiver) {
            context.unregisterReceiver(receiver);
        }

        public Handler getBackgroundHandler() {
            return BackgroundThread.getHandler();
        }

        public boolean isBrightnessModeAutomatic(ContentResolver resolver) {
            return Settings.System.getIntForUser(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE,
                    Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT)
                    == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
        }

        public int getSecureIntForUser(ContentResolver resolver, String setting, int defaultValue,
                int userId) {
            return Settings.Secure.getIntForUser(resolver, setting, defaultValue, userId);
        }

        public AtomicFile getFile(String filename) {
            return new AtomicFile(new File(Environment.getDataSystemDeDirectory(), filename));
        }

        public long currentTimeMillis() {
            return System.currentTimeMillis();
        }

        public long elapsedRealtimeNanos() {
            return SystemClock.elapsedRealtimeNanos();
        }

        public int getUserSerialNumber(UserManager userManager, int userId) {
            return userManager.getUserSerialNumber(userId);
        }

        public int getUserId(UserManager userManager, int userSerialNumber) {
            return userManager.getUserHandle(userSerialNumber);
        }

        public int[] getProfileIds(UserManager userManager, int userId) {
            if (userManager != null) {
                return userManager.getProfileIds(userId, false);
            } else {
                return new int[]{userId};
            }
        }

        public ActivityManager.StackInfo getFocusedStack() throws RemoteException {
            return ActivityManager.getService().getFocusedStackInfo();
        }

        public void scheduleIdleJob(Context context) {
            BrightnessIdleJob.scheduleJob(context);
        }

        public void cancelIdleJob(Context context) {
            BrightnessIdleJob.cancelJob(context);
        }

        public boolean isInteractive(Context context) {
            return context.getSystemService(PowerManager.class).isInteractive();
        }
    }
}
