/*
 * 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.app.ActivityTaskManager;
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.graphics.PixelFormat;
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.hardware.display.BrightnessConfiguration;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
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 android.view.Display;

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 com.android.server.LocalServices;

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.text.SimpleDateFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Date;
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 String ATTR_COLOR_SAMPLE_DURATION = "colorSampleDuration";
    private static final String ATTR_COLOR_VALUE_BUCKETS = "colorValueBuckets";

    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;
    private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;

    private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");

    private static final long COLOR_SAMPLE_DURATION = TimeUnit.SECONDS.toSeconds(10);
    // Sample chanel 2 of HSV which is the Value component.
    private static final int COLOR_SAMPLE_COMPONENT_MASK = 0x1 << 2;

    // 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 final UserManager mUserManager;
    private final Context mContext;
    private final ContentResolver mContentResolver;
    private final Handler mBgHandler;

    // These members should only be accessed on the mBgHandler thread.
    private BroadcastReceiver mBroadcastReceiver;
    private SensorListener mSensorListener;
    private SettingsObserver mSettingsObserver;
    private DisplayListener mDisplayListener;
    private boolean mSensorRegistered;
    private boolean mColorSamplingEnabled;
    private int mNoFramesToSample;
    private float mFrameRate;
    private BrightnessConfiguration mBrightnessConfiguration;
    // End of block of members that should only be accessed on the mBgHandler thread.

    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();
        }
        mBgHandler = new TrackerHandler(mInjector.getBackgroundHandler().getLooper());
        mUserManager = mContext.getSystemService(UserManager.class);
    }

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

    /**
     * Update tracker with new brightness configuration.
     */
    public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration) {
        mBgHandler.obtainMessage(MSG_BRIGHTNESS_CONFIG_CHANGED,
                brightnessConfiguration).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;
        }
        enableColorSampling();
    }

    /** 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;
        }
        disableColorSampling();
    }

    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,
                        mInjector.currentTimeMillis()));
        m.sendToTarget();
    }

    private void handleBrightnessChanged(float brightness, boolean userInitiated,
            float powerBrightnessFactor, boolean isUserSetBrightness,
            boolean isDefaultBrightnessConfig, long timestamp) {
        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(timestamp);
            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.isNightDisplayActivated(mContext));
        builder.setColorTemperature(mInjector.getNightDisplayColorTemperature(mContext));

        if (mColorSamplingEnabled) {
            DisplayedContentSample sample = mInjector.sampleColor(mNoFramesToSample);
            if (sample != null && sample.getSampleComponent(
                    DisplayedContentSample.ColorComponent.CHANNEL2) != null) {
                float numMillis = (sample.getNumFrames() / mFrameRate) * 1000.0f;
                builder.setColorValues(
                        sample.getSampleComponent(DisplayedContentSample.ColorComponent.CHANNEL2),
                        Math.round(numMillis));
            }
        }

        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());
                if (toWrite[i].colorValueBuckets != null
                        && toWrite[i].colorValueBuckets.length > 0) {
                    out.attribute(null, ATTR_COLOR_SAMPLE_DURATION,
                            Long.toString(toWrite[i].colorSampleDuration));
                    StringBuilder buckets = new StringBuilder();
                    for (int j = 0; j < toWrite[i].colorValueBuckets.length; ++j) {
                        if (j > 0) {
                            buckets.append(',');
                        }
                        buckets.append(Long.toString(toWrite[i].colorValueBuckets[j]));
                    }
                    out.attribute(null, ATTR_COLOR_VALUE_BUCKETS, buckets.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));
                    }

                    String colorSampleDurationString =
                            parser.getAttributeValue(null, ATTR_COLOR_SAMPLE_DURATION);
                    String colorValueBucketsString =
                            parser.getAttributeValue(null, ATTR_COLOR_VALUE_BUCKETS);
                    if (colorSampleDurationString != null && colorValueBucketsString != null) {
                        long colorSampleDuration = Long.parseLong(colorSampleDurationString);
                        String[] buckets = colorValueBucketsString.split(",");
                        long[] bucketValues = new long[buckets.length];
                        for (int i = 0; i < bucketValues.length; ++i) {
                            bucketValues[i] = Long.parseLong(buckets[i]);
                        }
                        builder.setColorValues(bucketValues, colorSampleDuration);
                    }

                    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(final PrintWriter pw) {
        pw.println("BrightnessTracker state:");
        synchronized (mDataCollectionLock) {
            pw.println("  mStarted=" + mStarted);
            pw.println("  mLastBatteryLevel=" + mLastBatteryLevel);
            pw.println("  mLastBrightness=" + mLastBrightness);
            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("    " + FORMAT.format(new Date(events[i].timeStamp)));
                pw.print(", userId=" + 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("}");
            }
        }
        pw.println("  mWriteBrightnessTrackerStateScheduled="
                + mWriteBrightnessTrackerStateScheduled);
        mBgHandler.runWithScissors(() -> dumpLocal(pw), 1000);
        if (mAmbientBrightnessStatsTracker != null) {
            pw.println();
            mAmbientBrightnessStatsTracker.dump(pw);
        }
    }

    private void dumpLocal(PrintWriter pw) {
        pw.println("  mSensorRegistered=" + mSensorRegistered);
        pw.println("  mColorSamplingEnabled=" + mColorSamplingEnabled);
        pw.println("  mNoFramesToSample=" + mNoFramesToSample);
        pw.println("  mFrameRate=" + mFrameRate);
    }

    private void enableColorSampling() {
        if (!mInjector.isBrightnessModeAutomatic(mContentResolver)
                || !mInjector.isInteractive(mContext)
                || mColorSamplingEnabled
                || mBrightnessConfiguration == null
                || !mBrightnessConfiguration.shouldCollectColorSamples()) {
            return;
        }

        mFrameRate = mInjector.getFrameRate(mContext);
        if (mFrameRate <= 0) {
            Slog.wtf(TAG, "Default display has a zero or negative framerate.");
            return;
        }
        mNoFramesToSample = (int) (mFrameRate * COLOR_SAMPLE_DURATION);

        DisplayedContentSamplingAttributes attributes = mInjector.getSamplingAttributes();
        if (DEBUG && attributes != null) {
            Slog.d(TAG, "Color sampling"
                    + " mask=0x" + Integer.toHexString(attributes.getComponentMask())
                    + " dataSpace=0x" + Integer.toHexString(attributes.getDataspace())
                    + " pixelFormat=0x" + Integer.toHexString(attributes.getPixelFormat()));
        }
        // Do we support sampling the Value component of HSV
        if (attributes != null && attributes.getPixelFormat() == PixelFormat.HSV_888
                && (attributes.getComponentMask() & COLOR_SAMPLE_COMPONENT_MASK) != 0) {

            mColorSamplingEnabled = mInjector.enableColorSampling(/* enable= */true,
                    mNoFramesToSample);
            if (DEBUG) {
                Slog.i(TAG, "turning on color sampling for "
                        + mNoFramesToSample + " frames, success=" + mColorSamplingEnabled);
            }
        }
        if (mColorSamplingEnabled && mDisplayListener == null) {
            mDisplayListener = new DisplayListener();
            mInjector.registerDisplayListener(mContext, mDisplayListener, mBgHandler);
        }
    }

    private void disableColorSampling() {
        if (!mColorSamplingEnabled) {
            return;
        }
        mInjector.enableColorSampling(/* enable= */ false, /* noFrames= */ 0);
        mColorSamplingEnabled = false;
        if (mDisplayListener != null) {
            mInjector.unRegisterDisplayListener(mContext, mDisplayListener);
            mDisplayListener = null;
        }
        if (DEBUG) {
            Slog.i(TAG, "turning off color sampling");
        }
    }

    private void updateColorSampling() {
        if (!mColorSamplingEnabled) {
            return;
        }
        float frameRate = mInjector.getFrameRate(mContext);
        if (frameRate != mFrameRate) {
            disableColorSampling();
            enableColorSampling();
        }
    }

    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 DisplayListener implements DisplayManager.DisplayListener {

        @Override
        public void onDisplayAdded(int displayId) {
            // Ignore
        }

        @Override
        public void onDisplayRemoved(int displayId) {
            // Ignore
        }

        @Override
        public void onDisplayChanged(int displayId) {
            if (displayId == Display.DEFAULT_DISPLAY) {
                updateColorSampling();
            }
        }
    }

    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, values.timestamp);
                    break;
                case MSG_START_SENSOR_LISTENER:
                    startSensorListener();
                    enableColorSampling();
                    break;
                case MSG_STOP_SENSOR_LISTENER:
                    stopSensorListener();
                    disableColorSampling();
                    break;
                case MSG_BRIGHTNESS_CONFIG_CHANGED:
                    mBrightnessConfiguration = (BrightnessConfiguration) msg.obj;
                    boolean shouldCollectColorSamples =
                            mBrightnessConfiguration != null
                                    && mBrightnessConfiguration.shouldCollectColorSamples();
                    if (shouldCollectColorSamples && !mColorSamplingEnabled) {
                        enableColorSampling();
                    } else if (!shouldCollectColorSamples && mColorSamplingEnabled) {
                        disableColorSampling();
                    }
                    break;

            }
        }
    }

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

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

    @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 ActivityTaskManager.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();
        }

        public int getNightDisplayColorTemperature(Context context) {
            return context.getSystemService(ColorDisplayManager.class)
                    .getNightDisplayColorTemperature();
        }

        public boolean isNightDisplayActivated(Context context) {
            return context.getSystemService(ColorDisplayManager.class).isNightDisplayActivated();
        }

        public DisplayedContentSample sampleColor(int noFramesToSample) {
            final DisplayManagerInternal displayManagerInternal =
                    LocalServices.getService(DisplayManagerInternal.class);
            return displayManagerInternal.getDisplayedContentSample(
                   Display.DEFAULT_DISPLAY, noFramesToSample, 0);
        }

        public float getFrameRate(Context context) {
            final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
            Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
            return display.getRefreshRate();
        }

        public DisplayedContentSamplingAttributes getSamplingAttributes() {
            final DisplayManagerInternal displayManagerInternal =
                    LocalServices.getService(DisplayManagerInternal.class);
            return displayManagerInternal.getDisplayedContentSamplingAttributes(
                    Display.DEFAULT_DISPLAY);
        }

        public boolean enableColorSampling(boolean enable, int noFrames) {
            final DisplayManagerInternal displayManagerInternal =
                    LocalServices.getService(DisplayManagerInternal.class);
            return displayManagerInternal.setDisplayedContentSamplingEnabled(
                    Display.DEFAULT_DISPLAY, enable, COLOR_SAMPLE_COMPONENT_MASK, noFrames);
        }

        public void registerDisplayListener(Context context,
                DisplayManager.DisplayListener listener, Handler handler) {
            final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
            displayManager.registerDisplayListener(listener, handler);
        }

        public void unRegisterDisplayListener(Context context,
                DisplayManager.DisplayListener listener) {
            final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
            displayManager.unregisterDisplayListener(listener);
        }
    }
}
