Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2017 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.server.display; |
| 18 | |
| 19 | import android.annotation.Nullable; |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 20 | import android.annotation.UserIdInt; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 21 | import android.app.ActivityManager; |
Wale Ogunwale | 04d9cb5 | 2018-04-30 13:55:07 -0700 | [diff] [blame] | 22 | import android.app.ActivityTaskManager; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 23 | import android.content.BroadcastReceiver; |
| 24 | import android.content.ContentResolver; |
| 25 | import android.content.Context; |
| 26 | import android.content.Intent; |
| 27 | import android.content.IntentFilter; |
| 28 | import android.content.pm.ParceledListSlice; |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 29 | import android.database.ContentObserver; |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 30 | import android.graphics.PixelFormat; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 31 | import android.hardware.Sensor; |
| 32 | import android.hardware.SensorEvent; |
| 33 | import android.hardware.SensorEventListener; |
| 34 | import android.hardware.SensorManager; |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 35 | import android.hardware.display.AmbientBrightnessDayStats; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 36 | import android.hardware.display.BrightnessChangeEvent; |
Kenny Guy | d6fd7d6 | 2019-11-13 15:33:19 +0000 | [diff] [blame] | 37 | import android.hardware.display.BrightnessConfiguration; |
Christine Franks | 71e003e | 2019-01-24 14:40:20 -0800 | [diff] [blame] | 38 | import android.hardware.display.ColorDisplayManager; |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 39 | import android.hardware.display.DisplayManager; |
| 40 | import android.hardware.display.DisplayManagerInternal; |
| 41 | import android.hardware.display.DisplayedContentSample; |
| 42 | import android.hardware.display.DisplayedContentSamplingAttributes; |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 43 | import android.net.Uri; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 44 | import android.os.BatteryManager; |
| 45 | import android.os.Environment; |
| 46 | import android.os.Handler; |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 47 | import android.os.Looper; |
| 48 | import android.os.Message; |
Kenny Guy | 689ab8f | 2017-11-29 12:12:06 +0000 | [diff] [blame] | 49 | import android.os.PowerManager; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 50 | import android.os.RemoteException; |
| 51 | import android.os.SystemClock; |
| 52 | import android.os.UserHandle; |
| 53 | import android.os.UserManager; |
| 54 | import android.provider.Settings; |
| 55 | import android.util.AtomicFile; |
| 56 | import android.util.Slog; |
| 57 | import android.util.Xml; |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 58 | import android.view.Display; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 59 | |
| 60 | import com.android.internal.annotations.GuardedBy; |
| 61 | import com.android.internal.annotations.VisibleForTesting; |
| 62 | import com.android.internal.os.BackgroundThread; |
| 63 | import com.android.internal.util.FastXmlSerializer; |
| 64 | import com.android.internal.util.RingBuffer; |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 65 | import com.android.server.LocalServices; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 66 | |
| 67 | import libcore.io.IoUtils; |
| 68 | |
| 69 | import org.xmlpull.v1.XmlPullParser; |
| 70 | import org.xmlpull.v1.XmlPullParserException; |
| 71 | import org.xmlpull.v1.XmlSerializer; |
| 72 | |
| 73 | import java.io.File; |
| 74 | import java.io.FileInputStream; |
| 75 | import java.io.FileOutputStream; |
| 76 | import java.io.IOException; |
| 77 | import java.io.InputStream; |
| 78 | import java.io.OutputStream; |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 79 | import java.io.PrintWriter; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 80 | import java.nio.charset.StandardCharsets; |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 81 | import java.text.SimpleDateFormat; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 82 | import java.util.ArrayDeque; |
| 83 | import java.util.ArrayList; |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 84 | import java.util.Date; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 85 | import java.util.Deque; |
Kenny Guy | 6c90d8a | 2018-02-20 16:53:27 +0000 | [diff] [blame] | 86 | import java.util.HashMap; |
| 87 | import java.util.Map; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 88 | import java.util.concurrent.TimeUnit; |
| 89 | |
| 90 | /** |
| 91 | * Class that tracks recent brightness settings changes and stores |
| 92 | * associated information such as light sensor readings. |
| 93 | */ |
| 94 | public class BrightnessTracker { |
| 95 | |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 96 | static final String TAG = "BrightnessTracker"; |
| 97 | static final boolean DEBUG = false; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 98 | |
| 99 | private static final String EVENTS_FILE = "brightness_events.xml"; |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 100 | private static final String AMBIENT_BRIGHTNESS_STATS_FILE = "ambient_brightness_stats.xml"; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 101 | private static final int MAX_EVENTS = 100; |
| 102 | // Discard events when reading or writing that are older than this. |
| 103 | private static final long MAX_EVENT_AGE = TimeUnit.DAYS.toMillis(30); |
| 104 | // Time over which we keep lux sensor readings. |
| 105 | private static final long LUX_EVENT_HORIZON = TimeUnit.SECONDS.toNanos(10); |
| 106 | |
| 107 | private static final String TAG_EVENTS = "events"; |
| 108 | private static final String TAG_EVENT = "event"; |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 109 | private static final String ATTR_NITS = "nits"; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 110 | private static final String ATTR_TIMESTAMP = "timestamp"; |
| 111 | private static final String ATTR_PACKAGE_NAME = "packageName"; |
| 112 | private static final String ATTR_USER = "user"; |
| 113 | private static final String ATTR_LUX = "lux"; |
| 114 | private static final String ATTR_LUX_TIMESTAMPS = "luxTimestamps"; |
| 115 | private static final String ATTR_BATTERY_LEVEL = "batteryLevel"; |
| 116 | private static final String ATTR_NIGHT_MODE = "nightMode"; |
| 117 | private static final String ATTR_COLOR_TEMPERATURE = "colorTemperature"; |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 118 | private static final String ATTR_LAST_NITS = "lastNits"; |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 119 | private static final String ATTR_DEFAULT_CONFIG = "defaultConfig"; |
| 120 | private static final String ATTR_POWER_SAVE = "powerSaveFactor"; |
| 121 | private static final String ATTR_USER_POINT = "userPoint"; |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 122 | private static final String ATTR_COLOR_SAMPLE_DURATION = "colorSampleDuration"; |
| 123 | private static final String ATTR_COLOR_VALUE_BUCKETS = "colorValueBuckets"; |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 124 | |
| 125 | private static final int MSG_BACKGROUND_START = 0; |
| 126 | private static final int MSG_BRIGHTNESS_CHANGED = 1; |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 127 | private static final int MSG_STOP_SENSOR_LISTENER = 2; |
| 128 | private static final int MSG_START_SENSOR_LISTENER = 3; |
Kenny Guy | d6fd7d6 | 2019-11-13 15:33:19 +0000 | [diff] [blame] | 129 | private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 130 | |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 131 | private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); |
| 132 | |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 133 | private static final long COLOR_SAMPLE_DURATION = TimeUnit.SECONDS.toSeconds(10); |
| 134 | // Sample chanel 2 of HSV which is the Value component. |
| 135 | private static final int COLOR_SAMPLE_COMPONENT_MASK = 0x1 << 2; |
| 136 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 137 | // Lock held while accessing mEvents, is held while writing events to flash. |
| 138 | private final Object mEventsLock = new Object(); |
| 139 | @GuardedBy("mEventsLock") |
| 140 | private RingBuffer<BrightnessChangeEvent> mEvents |
| 141 | = new RingBuffer<>(BrightnessChangeEvent.class, MAX_EVENTS); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 142 | @GuardedBy("mEventsLock") |
| 143 | private boolean mEventsDirty; |
Peeyush Agarwal | 8c2006d | 2018-02-08 12:39:39 +0000 | [diff] [blame] | 144 | |
| 145 | private volatile boolean mWriteBrightnessTrackerStateScheduled; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 146 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 147 | private AmbientBrightnessStatsTracker mAmbientBrightnessStatsTracker; |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 148 | |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 149 | private final UserManager mUserManager; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 150 | private final Context mContext; |
| 151 | private final ContentResolver mContentResolver; |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 152 | private final Handler mBgHandler; |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 153 | |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 154 | // These members should only be accessed on the mBgHandler thread. |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 155 | private BroadcastReceiver mBroadcastReceiver; |
| 156 | private SensorListener mSensorListener; |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 157 | private SettingsObserver mSettingsObserver; |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 158 | private DisplayListener mDisplayListener; |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 159 | private boolean mSensorRegistered; |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 160 | private boolean mColorSamplingEnabled; |
| 161 | private int mNoFramesToSample; |
| 162 | private float mFrameRate; |
Kenny Guy | d6fd7d6 | 2019-11-13 15:33:19 +0000 | [diff] [blame] | 163 | private BrightnessConfiguration mBrightnessConfiguration; |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 164 | // End of block of members that should only be accessed on the mBgHandler thread. |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 165 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 166 | private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 167 | |
| 168 | // Lock held while collecting data related to brightness changes. |
| 169 | private final Object mDataCollectionLock = new Object(); |
| 170 | @GuardedBy("mDataCollectionLock") |
| 171 | private Deque<LightData> mLastSensorReadings = new ArrayDeque<>(); |
| 172 | @GuardedBy("mDataCollectionLock") |
| 173 | private float mLastBatteryLevel = Float.NaN; |
| 174 | @GuardedBy("mDataCollectionLock") |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 175 | private float mLastBrightness = -1; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 176 | @GuardedBy("mDataCollectionLock") |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 177 | private boolean mStarted; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 178 | |
| 179 | private final Injector mInjector; |
| 180 | |
| 181 | public BrightnessTracker(Context context, @Nullable Injector injector) { |
| 182 | // Note this will be called very early in boot, other system |
| 183 | // services may not be present. |
| 184 | mContext = context; |
| 185 | mContentResolver = context.getContentResolver(); |
| 186 | if (injector != null) { |
| 187 | mInjector = injector; |
| 188 | } else { |
| 189 | mInjector = new Injector(); |
| 190 | } |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 191 | mBgHandler = new TrackerHandler(mInjector.getBackgroundHandler().getLooper()); |
| 192 | mUserManager = mContext.getSystemService(UserManager.class); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 193 | } |
| 194 | |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 195 | /** |
| 196 | * Start listening for brightness slider events |
| 197 | * |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 198 | * @param initialBrightness the initial screen brightness |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 199 | */ |
| 200 | public void start(float initialBrightness) { |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 201 | if (DEBUG) { |
| 202 | Slog.d(TAG, "Start"); |
| 203 | } |
Peeyush Agarwal | 8c2006d | 2018-02-08 12:39:39 +0000 | [diff] [blame] | 204 | mCurrentUserId = ActivityManager.getCurrentUser(); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 205 | mBgHandler.obtainMessage(MSG_BACKGROUND_START, (Float) initialBrightness).sendToTarget(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 206 | } |
| 207 | |
Kenny Guy | d6fd7d6 | 2019-11-13 15:33:19 +0000 | [diff] [blame] | 208 | /** |
| 209 | * Update tracker with new brightness configuration. |
| 210 | */ |
| 211 | public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration) { |
| 212 | mBgHandler.obtainMessage(MSG_BRIGHTNESS_CONFIG_CHANGED, |
| 213 | brightnessConfiguration).sendToTarget(); |
| 214 | } |
| 215 | |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 216 | private void backgroundStart(float initialBrightness) { |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 217 | readEvents(); |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 218 | readAmbientBrightnessStats(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 219 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 220 | mSensorListener = new SensorListener(); |
Kenny Guy | 689ab8f | 2017-11-29 12:12:06 +0000 | [diff] [blame] | 221 | |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 222 | mSettingsObserver = new SettingsObserver(mBgHandler); |
| 223 | mInjector.registerBrightnessModeObserver(mContentResolver, mSettingsObserver); |
| 224 | startSensorListener(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 225 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 226 | final IntentFilter intentFilter = new IntentFilter(); |
| 227 | intentFilter.addAction(Intent.ACTION_SHUTDOWN); |
| 228 | intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); |
Kenny Guy | 689ab8f | 2017-11-29 12:12:06 +0000 | [diff] [blame] | 229 | intentFilter.addAction(Intent.ACTION_SCREEN_ON); |
| 230 | intentFilter.addAction(Intent.ACTION_SCREEN_OFF); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 231 | mBroadcastReceiver = new Receiver(); |
| 232 | mInjector.registerReceiver(mContext, mBroadcastReceiver, intentFilter); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 233 | |
| 234 | mInjector.scheduleIdleJob(mContext); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 235 | synchronized (mDataCollectionLock) { |
| 236 | mLastBrightness = initialBrightness; |
| 237 | mStarted = true; |
| 238 | } |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 239 | enableColorSampling(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 240 | } |
| 241 | |
| 242 | /** Stop listening for events */ |
| 243 | @VisibleForTesting |
| 244 | void stop() { |
| 245 | if (DEBUG) { |
| 246 | Slog.d(TAG, "Stop"); |
| 247 | } |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 248 | mBgHandler.removeMessages(MSG_BACKGROUND_START); |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 249 | stopSensorListener(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 250 | mInjector.unregisterSensorListener(mContext, mSensorListener); |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 251 | mInjector.unregisterBrightnessModeObserver(mContext, mSettingsObserver); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 252 | mInjector.unregisterReceiver(mContext, mBroadcastReceiver); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 253 | mInjector.cancelIdleJob(mContext); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 254 | |
| 255 | synchronized (mDataCollectionLock) { |
| 256 | mStarted = false; |
| 257 | } |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 258 | disableColorSampling(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 259 | } |
| 260 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 261 | public void onSwitchUser(@UserIdInt int newUserId) { |
| 262 | if (DEBUG) { |
| 263 | Slog.d(TAG, "Used id updated from " + mCurrentUserId + " to " + newUserId); |
| 264 | } |
| 265 | mCurrentUserId = newUserId; |
| 266 | } |
| 267 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 268 | /** |
| 269 | * @param userId userId to fetch data for. |
Kenny Guy | 29aa30e | 2017-11-30 13:43:46 +0000 | [diff] [blame] | 270 | * @param includePackage if false we will null out BrightnessChangeEvent.packageName |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 271 | * @return List of recent {@link BrightnessChangeEvent}s |
| 272 | */ |
Kenny Guy | 29aa30e | 2017-11-30 13:43:46 +0000 | [diff] [blame] | 273 | public ParceledListSlice<BrightnessChangeEvent> getEvents(int userId, boolean includePackage) { |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 274 | BrightnessChangeEvent[] events; |
| 275 | synchronized (mEventsLock) { |
| 276 | events = mEvents.toArray(); |
| 277 | } |
Kenny Guy | 6c90d8a | 2018-02-20 16:53:27 +0000 | [diff] [blame] | 278 | int[] profiles = mInjector.getProfileIds(mUserManager, userId); |
| 279 | Map<Integer, Boolean> toRedact = new HashMap<>(); |
| 280 | for (int i = 0; i < profiles.length; ++i) { |
| 281 | int profileId = profiles[i]; |
| 282 | // Include slider interactions when a managed profile app is in the |
| 283 | // foreground but always redact the package name. |
| 284 | boolean redact = (!includePackage) || profileId != userId; |
| 285 | toRedact.put(profiles[i], redact); |
| 286 | } |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 287 | ArrayList<BrightnessChangeEvent> out = new ArrayList<>(events.length); |
| 288 | for (int i = 0; i < events.length; ++i) { |
Kenny Guy | 6c90d8a | 2018-02-20 16:53:27 +0000 | [diff] [blame] | 289 | Boolean redact = toRedact.get(events[i].userId); |
| 290 | if (redact != null) { |
| 291 | if (!redact) { |
Kenny Guy | 29aa30e | 2017-11-30 13:43:46 +0000 | [diff] [blame] | 292 | out.add(events[i]); |
| 293 | } else { |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 294 | BrightnessChangeEvent event = new BrightnessChangeEvent((events[i]), |
| 295 | /* redactPackage */ true); |
Kenny Guy | 29aa30e | 2017-11-30 13:43:46 +0000 | [diff] [blame] | 296 | out.add(event); |
| 297 | } |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 298 | } |
| 299 | } |
| 300 | return new ParceledListSlice<>(out); |
| 301 | } |
| 302 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 303 | public void persistBrightnessTrackerState() { |
| 304 | scheduleWriteBrightnessTrackerState(); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 305 | } |
| 306 | |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 307 | /** |
| 308 | * Notify the BrightnessTracker that the user has changed the brightness of the display. |
| 309 | */ |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 310 | public void notifyBrightnessChanged(float brightness, boolean userInitiated, |
| 311 | float powerBrightnessFactor, boolean isUserSetBrightness, |
| 312 | boolean isDefaultBrightnessConfig) { |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 313 | if (DEBUG) { |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 314 | Slog.d(TAG, String.format("notifyBrightnessChanged(brightness=%f, userInitiated=%b)", |
| 315 | brightness, userInitiated)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 316 | } |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 317 | Message m = mBgHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED, |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 318 | userInitiated ? 1 : 0, 0 /*unused*/, new BrightnessChangeValues(brightness, |
Kenny Guy | 2b326bf | 2018-04-18 18:42:10 +0100 | [diff] [blame] | 319 | powerBrightnessFactor, isUserSetBrightness, isDefaultBrightnessConfig, |
| 320 | mInjector.currentTimeMillis())); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 321 | m.sendToTarget(); |
| 322 | } |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 323 | |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 324 | private void handleBrightnessChanged(float brightness, boolean userInitiated, |
| 325 | float powerBrightnessFactor, boolean isUserSetBrightness, |
Kenny Guy | 2b326bf | 2018-04-18 18:42:10 +0100 | [diff] [blame] | 326 | boolean isDefaultBrightnessConfig, long timestamp) { |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 327 | BrightnessChangeEvent.Builder builder; |
| 328 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 329 | synchronized (mDataCollectionLock) { |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 330 | if (!mStarted) { |
| 331 | // Not currently gathering brightness change information |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 332 | return; |
| 333 | } |
| 334 | |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 335 | float previousBrightness = mLastBrightness; |
| 336 | mLastBrightness = brightness; |
| 337 | |
| 338 | if (!userInitiated) { |
| 339 | // We want to record what current brightness is so that we know what the user |
| 340 | // changed it from, but if it wasn't user initiated then we don't want to record it |
| 341 | // as a BrightnessChangeEvent. |
| 342 | return; |
| 343 | } |
| 344 | |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 345 | builder = new BrightnessChangeEvent.Builder(); |
| 346 | builder.setBrightness(brightness); |
Kenny Guy | 2b326bf | 2018-04-18 18:42:10 +0100 | [diff] [blame] | 347 | builder.setTimeStamp(timestamp); |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 348 | builder.setPowerBrightnessFactor(powerBrightnessFactor); |
| 349 | builder.setUserBrightnessPoint(isUserSetBrightness); |
| 350 | builder.setIsDefaultBrightnessConfig(isDefaultBrightnessConfig); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 351 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 352 | final int readingCount = mLastSensorReadings.size(); |
| 353 | if (readingCount == 0) { |
| 354 | // No sensor data so ignore this. |
| 355 | return; |
| 356 | } |
| 357 | |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 358 | float[] luxValues = new float[readingCount]; |
| 359 | long[] luxTimestamps = new long[readingCount]; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 360 | |
| 361 | int pos = 0; |
| 362 | |
| 363 | // Convert sensor timestamp in elapsed time nanos to current time millis. |
| 364 | long currentTimeMillis = mInjector.currentTimeMillis(); |
| 365 | long elapsedTimeNanos = mInjector.elapsedRealtimeNanos(); |
| 366 | for (LightData reading : mLastSensorReadings) { |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 367 | luxValues[pos] = reading.lux; |
| 368 | luxTimestamps[pos] = currentTimeMillis - |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 369 | TimeUnit.NANOSECONDS.toMillis(elapsedTimeNanos - reading.timestamp); |
| 370 | ++pos; |
| 371 | } |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 372 | builder.setLuxValues(luxValues); |
| 373 | builder.setLuxTimestamps(luxTimestamps); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 374 | |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 375 | builder.setBatteryLevel(mLastBatteryLevel); |
| 376 | builder.setLastBrightness(previousBrightness); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 377 | } |
| 378 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 379 | try { |
| 380 | final ActivityManager.StackInfo focusedStack = mInjector.getFocusedStack(); |
Kenny Guy | 0e875d3 | 2018-02-26 14:11:40 +0000 | [diff] [blame] | 381 | if (focusedStack != null && focusedStack.topActivity != null) { |
| 382 | builder.setUserId(focusedStack.userId); |
| 383 | builder.setPackageName(focusedStack.topActivity.getPackageName()); |
| 384 | } else { |
| 385 | // Ignore the event because we can't determine user / package. |
| 386 | if (DEBUG) { |
| 387 | Slog.d(TAG, "Ignoring event due to null focusedStack."); |
| 388 | } |
| 389 | return; |
| 390 | } |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 391 | } catch (RemoteException e) { |
| 392 | // Really shouldn't be possible. |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 393 | return; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 394 | } |
| 395 | |
Christine Franks | 71e003e | 2019-01-24 14:40:20 -0800 | [diff] [blame] | 396 | builder.setNightMode(mInjector.isNightDisplayActivated(mContext)); |
| 397 | builder.setColorTemperature(mInjector.getNightDisplayColorTemperature(mContext)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 398 | |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 399 | if (mColorSamplingEnabled) { |
| 400 | DisplayedContentSample sample = mInjector.sampleColor(mNoFramesToSample); |
| 401 | if (sample != null && sample.getSampleComponent( |
| 402 | DisplayedContentSample.ColorComponent.CHANNEL2) != null) { |
| 403 | float numMillis = (sample.getNumFrames() / mFrameRate) * 1000.0f; |
| 404 | builder.setColorValues( |
| 405 | sample.getSampleComponent(DisplayedContentSample.ColorComponent.CHANNEL2), |
| 406 | Math.round(numMillis)); |
| 407 | } |
| 408 | } |
| 409 | |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 410 | BrightnessChangeEvent event = builder.build(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 411 | if (DEBUG) { |
| 412 | Slog.d(TAG, "Event " + event.brightness + " " + event.packageName); |
| 413 | } |
| 414 | synchronized (mEventsLock) { |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 415 | mEventsDirty = true; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 416 | mEvents.append(event); |
| 417 | } |
| 418 | } |
| 419 | |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 420 | private void startSensorListener() { |
| 421 | if (!mSensorRegistered |
| 422 | && mInjector.isInteractive(mContext) |
| 423 | && mInjector.isBrightnessModeAutomatic(mContentResolver)) { |
| 424 | mAmbientBrightnessStatsTracker.start(); |
| 425 | mSensorRegistered = true; |
| 426 | mInjector.registerSensorListener(mContext, mSensorListener, |
| 427 | mInjector.getBackgroundHandler()); |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | private void stopSensorListener() { |
| 432 | if (mSensorRegistered) { |
| 433 | mAmbientBrightnessStatsTracker.stop(); |
| 434 | mInjector.unregisterSensorListener(mContext, mSensorListener); |
| 435 | mSensorRegistered = false; |
| 436 | } |
| 437 | } |
| 438 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 439 | private void scheduleWriteBrightnessTrackerState() { |
Peeyush Agarwal | 8c2006d | 2018-02-08 12:39:39 +0000 | [diff] [blame] | 440 | if (!mWriteBrightnessTrackerStateScheduled) { |
| 441 | mBgHandler.post(() -> { |
| 442 | mWriteBrightnessTrackerStateScheduled = false; |
| 443 | writeEvents(); |
| 444 | writeAmbientBrightnessStats(); |
| 445 | }); |
| 446 | mWriteBrightnessTrackerStateScheduled = true; |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 447 | } |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 448 | } |
| 449 | |
| 450 | private void writeEvents() { |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 451 | synchronized (mEventsLock) { |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 452 | if (!mEventsDirty) { |
| 453 | // Nothing to write |
| 454 | return; |
| 455 | } |
| 456 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 457 | final AtomicFile writeTo = mInjector.getFile(EVENTS_FILE); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 458 | if (writeTo == null) { |
| 459 | return; |
| 460 | } |
| 461 | if (mEvents.isEmpty()) { |
| 462 | if (writeTo.exists()) { |
| 463 | writeTo.delete(); |
| 464 | } |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 465 | mEventsDirty = false; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 466 | } else { |
| 467 | FileOutputStream output = null; |
| 468 | try { |
| 469 | output = writeTo.startWrite(); |
| 470 | writeEventsLocked(output); |
| 471 | writeTo.finishWrite(output); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 472 | mEventsDirty = false; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 473 | } catch (IOException e) { |
| 474 | writeTo.failWrite(output); |
| 475 | Slog.e(TAG, "Failed to write change mEvents.", e); |
| 476 | } |
| 477 | } |
| 478 | } |
| 479 | } |
| 480 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 481 | private void writeAmbientBrightnessStats() { |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 482 | final AtomicFile writeTo = mInjector.getFile(AMBIENT_BRIGHTNESS_STATS_FILE); |
| 483 | if (writeTo == null) { |
| 484 | return; |
| 485 | } |
| 486 | FileOutputStream output = null; |
| 487 | try { |
| 488 | output = writeTo.startWrite(); |
| 489 | mAmbientBrightnessStatsTracker.writeStats(output); |
| 490 | writeTo.finishWrite(output); |
| 491 | } catch (IOException e) { |
| 492 | writeTo.failWrite(output); |
| 493 | Slog.e(TAG, "Failed to write ambient brightness stats.", e); |
| 494 | } |
| 495 | } |
| 496 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 497 | private void readEvents() { |
| 498 | synchronized (mEventsLock) { |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 499 | // Read might prune events so mark as dirty. |
| 500 | mEventsDirty = true; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 501 | mEvents.clear(); |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 502 | final AtomicFile readFrom = mInjector.getFile(EVENTS_FILE); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 503 | if (readFrom != null && readFrom.exists()) { |
| 504 | FileInputStream input = null; |
| 505 | try { |
| 506 | input = readFrom.openRead(); |
| 507 | readEventsLocked(input); |
| 508 | } catch (IOException e) { |
| 509 | readFrom.delete(); |
| 510 | Slog.e(TAG, "Failed to read change mEvents.", e); |
| 511 | } finally { |
| 512 | IoUtils.closeQuietly(input); |
| 513 | } |
| 514 | } |
| 515 | } |
| 516 | } |
| 517 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 518 | private void readAmbientBrightnessStats() { |
| 519 | mAmbientBrightnessStatsTracker = new AmbientBrightnessStatsTracker(mUserManager, null); |
| 520 | final AtomicFile readFrom = mInjector.getFile(AMBIENT_BRIGHTNESS_STATS_FILE); |
| 521 | if (readFrom != null && readFrom.exists()) { |
| 522 | FileInputStream input = null; |
| 523 | try { |
| 524 | input = readFrom.openRead(); |
| 525 | mAmbientBrightnessStatsTracker.readStats(input); |
| 526 | } catch (IOException e) { |
| 527 | readFrom.delete(); |
| 528 | Slog.e(TAG, "Failed to read ambient brightness stats.", e); |
| 529 | } finally { |
| 530 | IoUtils.closeQuietly(input); |
| 531 | } |
| 532 | } |
| 533 | } |
| 534 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 535 | @VisibleForTesting |
| 536 | @GuardedBy("mEventsLock") |
| 537 | void writeEventsLocked(OutputStream stream) throws IOException { |
| 538 | XmlSerializer out = new FastXmlSerializer(); |
| 539 | out.setOutput(stream, StandardCharsets.UTF_8.name()); |
| 540 | out.startDocument(null, true); |
| 541 | out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); |
| 542 | |
| 543 | out.startTag(null, TAG_EVENTS); |
| 544 | BrightnessChangeEvent[] toWrite = mEvents.toArray(); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 545 | // Clear events, code below will add back the ones that are still within the time window. |
| 546 | mEvents.clear(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 547 | if (DEBUG) { |
| 548 | Slog.d(TAG, "Writing events " + toWrite.length); |
| 549 | } |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 550 | final long timeCutOff = mInjector.currentTimeMillis() - MAX_EVENT_AGE; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 551 | for (int i = 0; i < toWrite.length; ++i) { |
| 552 | int userSerialNo = mInjector.getUserSerialNumber(mUserManager, toWrite[i].userId); |
| 553 | if (userSerialNo != -1 && toWrite[i].timeStamp > timeCutOff) { |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 554 | mEvents.append(toWrite[i]); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 555 | out.startTag(null, TAG_EVENT); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 556 | out.attribute(null, ATTR_NITS, Float.toString(toWrite[i].brightness)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 557 | out.attribute(null, ATTR_TIMESTAMP, Long.toString(toWrite[i].timeStamp)); |
| 558 | out.attribute(null, ATTR_PACKAGE_NAME, toWrite[i].packageName); |
| 559 | out.attribute(null, ATTR_USER, Integer.toString(userSerialNo)); |
| 560 | out.attribute(null, ATTR_BATTERY_LEVEL, Float.toString(toWrite[i].batteryLevel)); |
| 561 | out.attribute(null, ATTR_NIGHT_MODE, Boolean.toString(toWrite[i].nightMode)); |
| 562 | out.attribute(null, ATTR_COLOR_TEMPERATURE, Integer.toString( |
| 563 | toWrite[i].colorTemperature)); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 564 | out.attribute(null, ATTR_LAST_NITS, |
| 565 | Float.toString(toWrite[i].lastBrightness)); |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 566 | out.attribute(null, ATTR_DEFAULT_CONFIG, |
| 567 | Boolean.toString(toWrite[i].isDefaultBrightnessConfig)); |
| 568 | out.attribute(null, ATTR_POWER_SAVE, |
| 569 | Float.toString(toWrite[i].powerBrightnessFactor)); |
| 570 | out.attribute(null, ATTR_USER_POINT, |
| 571 | Boolean.toString(toWrite[i].isUserSetBrightness)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 572 | StringBuilder luxValues = new StringBuilder(); |
| 573 | StringBuilder luxTimestamps = new StringBuilder(); |
| 574 | for (int j = 0; j < toWrite[i].luxValues.length; ++j) { |
| 575 | if (j > 0) { |
| 576 | luxValues.append(','); |
| 577 | luxTimestamps.append(','); |
| 578 | } |
| 579 | luxValues.append(Float.toString(toWrite[i].luxValues[j])); |
| 580 | luxTimestamps.append(Long.toString(toWrite[i].luxTimestamps[j])); |
| 581 | } |
| 582 | out.attribute(null, ATTR_LUX, luxValues.toString()); |
| 583 | out.attribute(null, ATTR_LUX_TIMESTAMPS, luxTimestamps.toString()); |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 584 | if (toWrite[i].colorValueBuckets != null |
| 585 | && toWrite[i].colorValueBuckets.length > 0) { |
| 586 | out.attribute(null, ATTR_COLOR_SAMPLE_DURATION, |
| 587 | Long.toString(toWrite[i].colorSampleDuration)); |
| 588 | StringBuilder buckets = new StringBuilder(); |
| 589 | for (int j = 0; j < toWrite[i].colorValueBuckets.length; ++j) { |
| 590 | if (j > 0) { |
| 591 | buckets.append(','); |
| 592 | } |
| 593 | buckets.append(Long.toString(toWrite[i].colorValueBuckets[j])); |
| 594 | } |
| 595 | out.attribute(null, ATTR_COLOR_VALUE_BUCKETS, buckets.toString()); |
| 596 | } |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 597 | out.endTag(null, TAG_EVENT); |
| 598 | } |
| 599 | } |
| 600 | out.endTag(null, TAG_EVENTS); |
| 601 | out.endDocument(); |
| 602 | stream.flush(); |
| 603 | } |
| 604 | |
| 605 | @VisibleForTesting |
| 606 | @GuardedBy("mEventsLock") |
| 607 | void readEventsLocked(InputStream stream) throws IOException { |
| 608 | try { |
| 609 | XmlPullParser parser = Xml.newPullParser(); |
| 610 | parser.setInput(stream, StandardCharsets.UTF_8.name()); |
| 611 | |
| 612 | int type; |
| 613 | while ((type = parser.next()) != XmlPullParser.END_DOCUMENT |
| 614 | && type != XmlPullParser.START_TAG) { |
| 615 | } |
| 616 | String tag = parser.getName(); |
| 617 | if (!TAG_EVENTS.equals(tag)) { |
| 618 | throw new XmlPullParserException( |
| 619 | "Events not found in brightness tracker file " + tag); |
| 620 | } |
| 621 | |
| 622 | final long timeCutOff = mInjector.currentTimeMillis() - MAX_EVENT_AGE; |
| 623 | |
| 624 | parser.next(); |
| 625 | int outerDepth = parser.getDepth(); |
| 626 | while ((type = parser.next()) != XmlPullParser.END_DOCUMENT |
| 627 | && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { |
| 628 | if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { |
| 629 | continue; |
| 630 | } |
| 631 | tag = parser.getName(); |
| 632 | if (TAG_EVENT.equals(tag)) { |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 633 | BrightnessChangeEvent.Builder builder = new BrightnessChangeEvent.Builder(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 634 | |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 635 | String brightness = parser.getAttributeValue(null, ATTR_NITS); |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 636 | builder.setBrightness(Float.parseFloat(brightness)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 637 | String timestamp = parser.getAttributeValue(null, ATTR_TIMESTAMP); |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 638 | builder.setTimeStamp(Long.parseLong(timestamp)); |
| 639 | builder.setPackageName(parser.getAttributeValue(null, ATTR_PACKAGE_NAME)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 640 | String user = parser.getAttributeValue(null, ATTR_USER); |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 641 | builder.setUserId(mInjector.getUserId(mUserManager, Integer.parseInt(user))); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 642 | String batteryLevel = parser.getAttributeValue(null, ATTR_BATTERY_LEVEL); |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 643 | builder.setBatteryLevel(Float.parseFloat(batteryLevel)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 644 | String nightMode = parser.getAttributeValue(null, ATTR_NIGHT_MODE); |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 645 | builder.setNightMode(Boolean.parseBoolean(nightMode)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 646 | String colorTemperature = |
| 647 | parser.getAttributeValue(null, ATTR_COLOR_TEMPERATURE); |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 648 | builder.setColorTemperature(Integer.parseInt(colorTemperature)); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 649 | String lastBrightness = parser.getAttributeValue(null, ATTR_LAST_NITS); |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 650 | builder.setLastBrightness(Float.parseFloat(lastBrightness)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 651 | |
| 652 | String luxValue = parser.getAttributeValue(null, ATTR_LUX); |
| 653 | String luxTimestamp = parser.getAttributeValue(null, ATTR_LUX_TIMESTAMPS); |
| 654 | |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 655 | String[] luxValuesStrings = luxValue.split(","); |
| 656 | String[] luxTimestampsStrings = luxTimestamp.split(","); |
| 657 | if (luxValuesStrings.length != luxTimestampsStrings.length) { |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 658 | continue; |
| 659 | } |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 660 | float[] luxValues = new float[luxValuesStrings.length]; |
| 661 | long[] luxTimestamps = new long[luxValuesStrings.length]; |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 662 | for (int i = 0; i < luxValues.length; ++i) { |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 663 | luxValues[i] = Float.parseFloat(luxValuesStrings[i]); |
| 664 | luxTimestamps[i] = Long.parseLong(luxTimestampsStrings[i]); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 665 | } |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 666 | builder.setLuxValues(luxValues); |
| 667 | builder.setLuxTimestamps(luxTimestamps); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 668 | |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 669 | String defaultConfig = parser.getAttributeValue(null, ATTR_DEFAULT_CONFIG); |
| 670 | if (defaultConfig != null) { |
| 671 | builder.setIsDefaultBrightnessConfig(Boolean.parseBoolean(defaultConfig)); |
| 672 | } |
| 673 | String powerSave = parser.getAttributeValue(null, ATTR_POWER_SAVE); |
| 674 | if (powerSave != null) { |
| 675 | builder.setPowerBrightnessFactor(Float.parseFloat(powerSave)); |
| 676 | } else { |
| 677 | builder.setPowerBrightnessFactor(1.0f); |
| 678 | } |
| 679 | String userPoint = parser.getAttributeValue(null, ATTR_USER_POINT); |
| 680 | if (userPoint != null) { |
| 681 | builder.setUserBrightnessPoint(Boolean.parseBoolean(userPoint)); |
| 682 | } |
| 683 | |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 684 | String colorSampleDurationString = |
| 685 | parser.getAttributeValue(null, ATTR_COLOR_SAMPLE_DURATION); |
| 686 | String colorValueBucketsString = |
| 687 | parser.getAttributeValue(null, ATTR_COLOR_VALUE_BUCKETS); |
| 688 | if (colorSampleDurationString != null && colorValueBucketsString != null) { |
| 689 | long colorSampleDuration = Long.parseLong(colorSampleDurationString); |
| 690 | String[] buckets = colorValueBucketsString.split(","); |
| 691 | long[] bucketValues = new long[buckets.length]; |
| 692 | for (int i = 0; i < bucketValues.length; ++i) { |
| 693 | bucketValues[i] = Long.parseLong(buckets[i]); |
| 694 | } |
| 695 | builder.setColorValues(bucketValues, colorSampleDuration); |
| 696 | } |
| 697 | |
Kenny Guy | 0ff4489 | 2018-01-10 14:06:42 +0000 | [diff] [blame] | 698 | BrightnessChangeEvent event = builder.build(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 699 | if (DEBUG) { |
| 700 | Slog.i(TAG, "Read event " + event.brightness |
| 701 | + " " + event.packageName); |
| 702 | } |
| 703 | |
| 704 | if (event.userId != -1 && event.timeStamp > timeCutOff |
| 705 | && event.luxValues.length > 0) { |
| 706 | mEvents.append(event); |
| 707 | } |
| 708 | } |
| 709 | } |
| 710 | } catch (NullPointerException | NumberFormatException | XmlPullParserException |
| 711 | | IOException e) { |
| 712 | // Failed to parse something, just start with an empty event log. |
| 713 | mEvents = new RingBuffer<>(BrightnessChangeEvent.class, MAX_EVENTS); |
| 714 | Slog.e(TAG, "Failed to parse brightness event", e); |
| 715 | // Re-throw so we will delete the bad file. |
| 716 | throw new IOException("failed to parse file", e); |
| 717 | } |
| 718 | } |
| 719 | |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 720 | public void dump(final PrintWriter pw) { |
Kenny Guy | e1674e5 | 2017-11-30 16:25:26 +0000 | [diff] [blame] | 721 | pw.println("BrightnessTracker state:"); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 722 | synchronized (mDataCollectionLock) { |
Kenny Guy | 05ce809 | 2018-01-17 13:44:20 +0000 | [diff] [blame] | 723 | pw.println(" mStarted=" + mStarted); |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 724 | pw.println(" mLastBatteryLevel=" + mLastBatteryLevel); |
| 725 | pw.println(" mLastBrightness=" + mLastBrightness); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 726 | pw.println(" mLastSensorReadings.size=" + mLastSensorReadings.size()); |
Kenny Guy | e1674e5 | 2017-11-30 16:25:26 +0000 | [diff] [blame] | 727 | if (!mLastSensorReadings.isEmpty()) { |
| 728 | pw.println(" mLastSensorReadings time span " |
| 729 | + mLastSensorReadings.peekFirst().timestamp + "->" |
| 730 | + mLastSensorReadings.peekLast().timestamp); |
| 731 | } |
| 732 | } |
| 733 | synchronized (mEventsLock) { |
| 734 | pw.println(" mEventsDirty=" + mEventsDirty); |
| 735 | pw.println(" mEvents.size=" + mEvents.size()); |
| 736 | BrightnessChangeEvent[] events = mEvents.toArray(); |
| 737 | for (int i = 0; i < events.length; ++i) { |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 738 | pw.print(" " + FORMAT.format(new Date(events[i].timeStamp))); |
| 739 | pw.print(", userId=" + events[i].userId); |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 740 | pw.print(", " + events[i].lastBrightness + "->" + events[i].brightness); |
| 741 | pw.print(", isUserSetBrightness=" + events[i].isUserSetBrightness); |
| 742 | pw.print(", powerBrightnessFactor=" + events[i].powerBrightnessFactor); |
| 743 | pw.print(", isDefaultBrightnessConfig=" + events[i].isDefaultBrightnessConfig); |
| 744 | pw.print(" {"); |
Kenny Guy | e1674e5 | 2017-11-30 16:25:26 +0000 | [diff] [blame] | 745 | for (int j = 0; j < events[i].luxValues.length; ++j){ |
| 746 | if (j != 0) { |
| 747 | pw.print(", "); |
| 748 | } |
| 749 | pw.print("(" + events[i].luxValues[j] + "," + events[i].luxTimestamps[j] + ")"); |
| 750 | } |
| 751 | pw.println("}"); |
| 752 | } |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 753 | } |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 754 | pw.println(" mWriteBrightnessTrackerStateScheduled=" |
| 755 | + mWriteBrightnessTrackerStateScheduled); |
| 756 | mBgHandler.runWithScissors(() -> dumpLocal(pw), 1000); |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 757 | if (mAmbientBrightnessStatsTracker != null) { |
Peeyush Agarwal | 8c2006d | 2018-02-08 12:39:39 +0000 | [diff] [blame] | 758 | pw.println(); |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 759 | mAmbientBrightnessStatsTracker.dump(pw); |
| 760 | } |
| 761 | } |
| 762 | |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 763 | private void dumpLocal(PrintWriter pw) { |
| 764 | pw.println(" mSensorRegistered=" + mSensorRegistered); |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 765 | pw.println(" mColorSamplingEnabled=" + mColorSamplingEnabled); |
| 766 | pw.println(" mNoFramesToSample=" + mNoFramesToSample); |
| 767 | pw.println(" mFrameRate=" + mFrameRate); |
| 768 | } |
| 769 | |
| 770 | private void enableColorSampling() { |
| 771 | if (!mInjector.isBrightnessModeAutomatic(mContentResolver) |
| 772 | || !mInjector.isInteractive(mContext) |
Kenny Guy | d6fd7d6 | 2019-11-13 15:33:19 +0000 | [diff] [blame] | 773 | || mColorSamplingEnabled |
| 774 | || mBrightnessConfiguration == null |
| 775 | || !mBrightnessConfiguration.shouldCollectColorSamples()) { |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 776 | return; |
| 777 | } |
| 778 | |
| 779 | mFrameRate = mInjector.getFrameRate(mContext); |
| 780 | if (mFrameRate <= 0) { |
| 781 | Slog.wtf(TAG, "Default display has a zero or negative framerate."); |
| 782 | return; |
| 783 | } |
| 784 | mNoFramesToSample = (int) (mFrameRate * COLOR_SAMPLE_DURATION); |
| 785 | |
| 786 | DisplayedContentSamplingAttributes attributes = mInjector.getSamplingAttributes(); |
| 787 | if (DEBUG && attributes != null) { |
| 788 | Slog.d(TAG, "Color sampling" |
| 789 | + " mask=0x" + Integer.toHexString(attributes.getComponentMask()) |
| 790 | + " dataSpace=0x" + Integer.toHexString(attributes.getDataspace()) |
| 791 | + " pixelFormat=0x" + Integer.toHexString(attributes.getPixelFormat())); |
| 792 | } |
| 793 | // Do we support sampling the Value component of HSV |
| 794 | if (attributes != null && attributes.getPixelFormat() == PixelFormat.HSV_888 |
| 795 | && (attributes.getComponentMask() & COLOR_SAMPLE_COMPONENT_MASK) != 0) { |
| 796 | |
| 797 | mColorSamplingEnabled = mInjector.enableColorSampling(/* enable= */true, |
| 798 | mNoFramesToSample); |
| 799 | if (DEBUG) { |
| 800 | Slog.i(TAG, "turning on color sampling for " |
| 801 | + mNoFramesToSample + " frames, success=" + mColorSamplingEnabled); |
| 802 | } |
| 803 | } |
| 804 | if (mColorSamplingEnabled && mDisplayListener == null) { |
| 805 | mDisplayListener = new DisplayListener(); |
| 806 | mInjector.registerDisplayListener(mContext, mDisplayListener, mBgHandler); |
| 807 | } |
| 808 | } |
| 809 | |
| 810 | private void disableColorSampling() { |
| 811 | if (!mColorSamplingEnabled) { |
| 812 | return; |
| 813 | } |
| 814 | mInjector.enableColorSampling(/* enable= */ false, /* noFrames= */ 0); |
| 815 | mColorSamplingEnabled = false; |
| 816 | if (mDisplayListener != null) { |
| 817 | mInjector.unRegisterDisplayListener(mContext, mDisplayListener); |
| 818 | mDisplayListener = null; |
| 819 | } |
| 820 | if (DEBUG) { |
| 821 | Slog.i(TAG, "turning off color sampling"); |
| 822 | } |
| 823 | } |
| 824 | |
| 825 | private void updateColorSampling() { |
| 826 | if (!mColorSamplingEnabled) { |
| 827 | return; |
| 828 | } |
| 829 | float frameRate = mInjector.getFrameRate(mContext); |
| 830 | if (frameRate != mFrameRate) { |
| 831 | disableColorSampling(); |
| 832 | enableColorSampling(); |
| 833 | } |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 834 | } |
| 835 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 836 | public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(int userId) { |
Kenny Guy | 637f8be | 2018-04-03 13:16:58 +0100 | [diff] [blame] | 837 | if (mAmbientBrightnessStatsTracker != null) { |
| 838 | ArrayList<AmbientBrightnessDayStats> stats = |
Michael Wright | 2155bc2 | 2018-05-01 00:38:32 +0100 | [diff] [blame] | 839 | mAmbientBrightnessStatsTracker.getUserStats(userId); |
Kenny Guy | 637f8be | 2018-04-03 13:16:58 +0100 | [diff] [blame] | 840 | if (stats != null) { |
| 841 | return new ParceledListSlice<>(stats); |
| 842 | } |
| 843 | } |
| 844 | return ParceledListSlice.emptyList(); |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 845 | } |
| 846 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 847 | // Not allowed to keep the SensorEvent so used to copy the data we care about. |
| 848 | private static class LightData { |
| 849 | public float lux; |
| 850 | // Time in elapsedRealtimeNanos |
| 851 | public long timestamp; |
| 852 | } |
| 853 | |
| 854 | private void recordSensorEvent(SensorEvent event) { |
| 855 | long horizon = mInjector.elapsedRealtimeNanos() - LUX_EVENT_HORIZON; |
| 856 | synchronized (mDataCollectionLock) { |
| 857 | if (DEBUG) { |
| 858 | Slog.v(TAG, "Sensor event " + event); |
| 859 | } |
| 860 | if (!mLastSensorReadings.isEmpty() |
| 861 | && event.timestamp < mLastSensorReadings.getLast().timestamp) { |
| 862 | // Ignore event that came out of order. |
| 863 | return; |
| 864 | } |
| 865 | LightData data = null; |
| 866 | while (!mLastSensorReadings.isEmpty() |
| 867 | && mLastSensorReadings.getFirst().timestamp < horizon) { |
| 868 | // Remove data that has fallen out of the window. |
| 869 | data = mLastSensorReadings.removeFirst(); |
| 870 | } |
| 871 | // We put back the last one we removed so we know how long |
| 872 | // the first sensor reading was valid for. |
| 873 | if (data != null) { |
| 874 | mLastSensorReadings.addFirst(data); |
| 875 | } |
| 876 | |
| 877 | data = new LightData(); |
| 878 | data.timestamp = event.timestamp; |
| 879 | data.lux = event.values[0]; |
| 880 | mLastSensorReadings.addLast(data); |
| 881 | } |
| 882 | } |
| 883 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 884 | private void recordAmbientBrightnessStats(SensorEvent event) { |
| 885 | mAmbientBrightnessStatsTracker.add(mCurrentUserId, event.values[0]); |
| 886 | } |
| 887 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 888 | private void batteryLevelChanged(int level, int scale) { |
| 889 | synchronized (mDataCollectionLock) { |
| 890 | mLastBatteryLevel = (float) level / (float) scale; |
| 891 | } |
| 892 | } |
| 893 | |
| 894 | private final class SensorListener implements SensorEventListener { |
| 895 | @Override |
| 896 | public void onSensorChanged(SensorEvent event) { |
| 897 | recordSensorEvent(event); |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 898 | recordAmbientBrightnessStats(event); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 899 | } |
| 900 | |
| 901 | @Override |
| 902 | public void onAccuracyChanged(Sensor sensor, int accuracy) { |
| 903 | |
| 904 | } |
| 905 | } |
| 906 | |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 907 | private final class DisplayListener implements DisplayManager.DisplayListener { |
| 908 | |
| 909 | @Override |
| 910 | public void onDisplayAdded(int displayId) { |
| 911 | // Ignore |
| 912 | } |
| 913 | |
| 914 | @Override |
| 915 | public void onDisplayRemoved(int displayId) { |
| 916 | // Ignore |
| 917 | } |
| 918 | |
| 919 | @Override |
| 920 | public void onDisplayChanged(int displayId) { |
| 921 | if (displayId == Display.DEFAULT_DISPLAY) { |
| 922 | updateColorSampling(); |
| 923 | } |
| 924 | } |
| 925 | } |
| 926 | |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 927 | private final class SettingsObserver extends ContentObserver { |
| 928 | public SettingsObserver(Handler handler) { |
| 929 | super(handler); |
| 930 | } |
| 931 | |
| 932 | @Override |
| 933 | public void onChange(boolean selfChange, Uri uri) { |
| 934 | if (DEBUG) { |
| 935 | Slog.v(TAG, "settings change " + uri); |
| 936 | } |
| 937 | if (mInjector.isBrightnessModeAutomatic(mContentResolver)) { |
| 938 | mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); |
| 939 | } else { |
| 940 | mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); |
| 941 | } |
| 942 | } |
| 943 | } |
| 944 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 945 | private final class Receiver extends BroadcastReceiver { |
| 946 | @Override |
| 947 | public void onReceive(Context context, Intent intent) { |
| 948 | if (DEBUG) { |
| 949 | Slog.d(TAG, "Received " + intent.getAction()); |
| 950 | } |
| 951 | String action = intent.getAction(); |
| 952 | if (Intent.ACTION_SHUTDOWN.equals(action)) { |
| 953 | stop(); |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 954 | scheduleWriteBrightnessTrackerState(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 955 | } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { |
| 956 | int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); |
| 957 | int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0); |
| 958 | if (level != -1 && scale != 0) { |
| 959 | batteryLevelChanged(level, scale); |
| 960 | } |
Kenny Guy | 689ab8f | 2017-11-29 12:12:06 +0000 | [diff] [blame] | 961 | } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 962 | mBgHandler.obtainMessage(MSG_STOP_SENSOR_LISTENER).sendToTarget(); |
Kenny Guy | 689ab8f | 2017-11-29 12:12:06 +0000 | [diff] [blame] | 963 | } else if (Intent.ACTION_SCREEN_ON.equals(action)) { |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 964 | mBgHandler.obtainMessage(MSG_START_SENSOR_LISTENER).sendToTarget(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 965 | } |
| 966 | } |
| 967 | } |
| 968 | |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 969 | private final class TrackerHandler extends Handler { |
| 970 | public TrackerHandler(Looper looper) { |
| 971 | super(looper, null, true /*async*/); |
| 972 | } |
| 973 | public void handleMessage(Message msg) { |
| 974 | switch (msg.what) { |
| 975 | case MSG_BACKGROUND_START: |
| 976 | backgroundStart((float)msg.obj /*initial brightness*/); |
| 977 | break; |
| 978 | case MSG_BRIGHTNESS_CHANGED: |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 979 | BrightnessChangeValues values = (BrightnessChangeValues) msg.obj; |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 980 | boolean userInitiatedChange = (msg.arg1 == 1); |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 981 | handleBrightnessChanged(values.brightness, userInitiatedChange, |
| 982 | values.powerBrightnessFactor, values.isUserSetBrightness, |
Kenny Guy | 2b326bf | 2018-04-18 18:42:10 +0100 | [diff] [blame] | 983 | values.isDefaultBrightnessConfig, values.timestamp); |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 984 | break; |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 985 | case MSG_START_SENSOR_LISTENER: |
| 986 | startSensorListener(); |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 987 | enableColorSampling(); |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 988 | break; |
| 989 | case MSG_STOP_SENSOR_LISTENER: |
| 990 | stopSensorListener(); |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 991 | disableColorSampling(); |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 992 | break; |
Kenny Guy | d6fd7d6 | 2019-11-13 15:33:19 +0000 | [diff] [blame] | 993 | case MSG_BRIGHTNESS_CONFIG_CHANGED: |
| 994 | mBrightnessConfiguration = (BrightnessConfiguration) msg.obj; |
| 995 | boolean shouldCollectColorSamples = |
| 996 | mBrightnessConfiguration != null |
| 997 | && mBrightnessConfiguration.shouldCollectColorSamples(); |
| 998 | if (shouldCollectColorSamples && !mColorSamplingEnabled) { |
| 999 | enableColorSampling(); |
| 1000 | } else if (!shouldCollectColorSamples && mColorSamplingEnabled) { |
| 1001 | disableColorSampling(); |
| 1002 | } |
| 1003 | break; |
| 1004 | |
Michael Wright | 144aac9 | 2017-12-21 18:37:41 +0000 | [diff] [blame] | 1005 | } |
| 1006 | } |
| 1007 | } |
| 1008 | |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 1009 | private static class BrightnessChangeValues { |
| 1010 | final float brightness; |
| 1011 | final float powerBrightnessFactor; |
| 1012 | final boolean isUserSetBrightness; |
| 1013 | final boolean isDefaultBrightnessConfig; |
Kenny Guy | 2b326bf | 2018-04-18 18:42:10 +0100 | [diff] [blame] | 1014 | final long timestamp; |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 1015 | |
| 1016 | BrightnessChangeValues(float brightness, float powerBrightnessFactor, |
Kenny Guy | 2b326bf | 2018-04-18 18:42:10 +0100 | [diff] [blame] | 1017 | boolean isUserSetBrightness, boolean isDefaultBrightnessConfig, |
| 1018 | long timestamp) { |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 1019 | this.brightness = brightness; |
| 1020 | this.powerBrightnessFactor = powerBrightnessFactor; |
| 1021 | this.isUserSetBrightness = isUserSetBrightness; |
| 1022 | this.isDefaultBrightnessConfig = isDefaultBrightnessConfig; |
Kenny Guy | 2b326bf | 2018-04-18 18:42:10 +0100 | [diff] [blame] | 1023 | this.timestamp = timestamp; |
Kenny Guy | 53d0661 | 2018-01-30 14:19:13 +0000 | [diff] [blame] | 1024 | } |
| 1025 | } |
| 1026 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1027 | @VisibleForTesting |
| 1028 | static class Injector { |
| 1029 | public void registerSensorListener(Context context, |
Kenny Guy | 689ab8f | 2017-11-29 12:12:06 +0000 | [diff] [blame] | 1030 | SensorEventListener sensorListener, Handler handler) { |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1031 | SensorManager sensorManager = context.getSystemService(SensorManager.class); |
| 1032 | Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); |
| 1033 | sensorManager.registerListener(sensorListener, |
Kenny Guy | 689ab8f | 2017-11-29 12:12:06 +0000 | [diff] [blame] | 1034 | lightSensor, SensorManager.SENSOR_DELAY_NORMAL, handler); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1035 | } |
| 1036 | |
| 1037 | public void unregisterSensorListener(Context context, SensorEventListener sensorListener) { |
| 1038 | SensorManager sensorManager = context.getSystemService(SensorManager.class); |
| 1039 | sensorManager.unregisterListener(sensorListener); |
| 1040 | } |
| 1041 | |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 1042 | public void registerBrightnessModeObserver(ContentResolver resolver, |
| 1043 | ContentObserver settingsObserver) { |
| 1044 | resolver.registerContentObserver(Settings.System.getUriFor( |
| 1045 | Settings.System.SCREEN_BRIGHTNESS_MODE), |
| 1046 | false, settingsObserver, UserHandle.USER_ALL); |
| 1047 | } |
| 1048 | |
| 1049 | public void unregisterBrightnessModeObserver(Context context, |
| 1050 | ContentObserver settingsObserver) { |
| 1051 | context.getContentResolver().unregisterContentObserver(settingsObserver); |
| 1052 | } |
| 1053 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1054 | public void registerReceiver(Context context, |
| 1055 | BroadcastReceiver receiver, IntentFilter filter) { |
| 1056 | context.registerReceiver(receiver, filter); |
| 1057 | } |
| 1058 | |
| 1059 | public void unregisterReceiver(Context context, |
| 1060 | BroadcastReceiver receiver) { |
| 1061 | context.unregisterReceiver(receiver); |
| 1062 | } |
| 1063 | |
| 1064 | public Handler getBackgroundHandler() { |
| 1065 | return BackgroundThread.getHandler(); |
| 1066 | } |
| 1067 | |
Kenny Guy | 3d7172c | 2018-03-19 14:18:23 +0000 | [diff] [blame] | 1068 | public boolean isBrightnessModeAutomatic(ContentResolver resolver) { |
| 1069 | return Settings.System.getIntForUser(resolver, Settings.System.SCREEN_BRIGHTNESS_MODE, |
| 1070 | Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT) |
| 1071 | == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; |
| 1072 | } |
| 1073 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1074 | public int getSecureIntForUser(ContentResolver resolver, String setting, int defaultValue, |
| 1075 | int userId) { |
| 1076 | return Settings.Secure.getIntForUser(resolver, setting, defaultValue, userId); |
| 1077 | } |
| 1078 | |
Peeyush Agarwal | cc155dd | 2018-01-10 11:51:33 +0000 | [diff] [blame] | 1079 | public AtomicFile getFile(String filename) { |
| 1080 | return new AtomicFile(new File(Environment.getDataSystemDeDirectory(), filename)); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1081 | } |
| 1082 | |
| 1083 | public long currentTimeMillis() { |
| 1084 | return System.currentTimeMillis(); |
| 1085 | } |
| 1086 | |
| 1087 | public long elapsedRealtimeNanos() { |
| 1088 | return SystemClock.elapsedRealtimeNanos(); |
| 1089 | } |
| 1090 | |
| 1091 | public int getUserSerialNumber(UserManager userManager, int userId) { |
| 1092 | return userManager.getUserSerialNumber(userId); |
| 1093 | } |
| 1094 | |
| 1095 | public int getUserId(UserManager userManager, int userSerialNumber) { |
| 1096 | return userManager.getUserHandle(userSerialNumber); |
| 1097 | } |
| 1098 | |
Kenny Guy | 6c90d8a | 2018-02-20 16:53:27 +0000 | [diff] [blame] | 1099 | public int[] getProfileIds(UserManager userManager, int userId) { |
| 1100 | if (userManager != null) { |
| 1101 | return userManager.getProfileIds(userId, false); |
| 1102 | } else { |
| 1103 | return new int[]{userId}; |
| 1104 | } |
| 1105 | } |
| 1106 | |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1107 | public ActivityManager.StackInfo getFocusedStack() throws RemoteException { |
Wale Ogunwale | 04d9cb5 | 2018-04-30 13:55:07 -0700 | [diff] [blame] | 1108 | return ActivityTaskManager.getService().getFocusedStackInfo(); |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1109 | } |
Kenny Guy | cfe7b70 | 2017-11-14 21:04:58 +0000 | [diff] [blame] | 1110 | |
| 1111 | public void scheduleIdleJob(Context context) { |
| 1112 | BrightnessIdleJob.scheduleJob(context); |
| 1113 | } |
| 1114 | |
| 1115 | public void cancelIdleJob(Context context) { |
| 1116 | BrightnessIdleJob.cancelJob(context); |
| 1117 | } |
Kenny Guy | 689ab8f | 2017-11-29 12:12:06 +0000 | [diff] [blame] | 1118 | |
| 1119 | public boolean isInteractive(Context context) { |
| 1120 | return context.getSystemService(PowerManager.class).isInteractive(); |
| 1121 | } |
Kenny Guy | 2385d4f | 2018-08-15 14:35:11 +0100 | [diff] [blame] | 1122 | |
Christine Franks | 71e003e | 2019-01-24 14:40:20 -0800 | [diff] [blame] | 1123 | public int getNightDisplayColorTemperature(Context context) { |
| 1124 | return context.getSystemService(ColorDisplayManager.class) |
| 1125 | .getNightDisplayColorTemperature(); |
Kenny Guy | 2385d4f | 2018-08-15 14:35:11 +0100 | [diff] [blame] | 1126 | } |
| 1127 | |
Christine Franks | 71e003e | 2019-01-24 14:40:20 -0800 | [diff] [blame] | 1128 | public boolean isNightDisplayActivated(Context context) { |
| 1129 | return context.getSystemService(ColorDisplayManager.class).isNightDisplayActivated(); |
Kenny Guy | 2385d4f | 2018-08-15 14:35:11 +0100 | [diff] [blame] | 1130 | } |
Kenny Guy | 908108a | 2019-01-17 12:56:34 +0000 | [diff] [blame] | 1131 | |
| 1132 | public DisplayedContentSample sampleColor(int noFramesToSample) { |
| 1133 | final DisplayManagerInternal displayManagerInternal = |
| 1134 | LocalServices.getService(DisplayManagerInternal.class); |
| 1135 | return displayManagerInternal.getDisplayedContentSample( |
| 1136 | Display.DEFAULT_DISPLAY, noFramesToSample, 0); |
| 1137 | } |
| 1138 | |
| 1139 | public float getFrameRate(Context context) { |
| 1140 | final DisplayManager displayManager = context.getSystemService(DisplayManager.class); |
| 1141 | Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY); |
| 1142 | return display.getRefreshRate(); |
| 1143 | } |
| 1144 | |
| 1145 | public DisplayedContentSamplingAttributes getSamplingAttributes() { |
| 1146 | final DisplayManagerInternal displayManagerInternal = |
| 1147 | LocalServices.getService(DisplayManagerInternal.class); |
| 1148 | return displayManagerInternal.getDisplayedContentSamplingAttributes( |
| 1149 | Display.DEFAULT_DISPLAY); |
| 1150 | } |
| 1151 | |
| 1152 | public boolean enableColorSampling(boolean enable, int noFrames) { |
| 1153 | final DisplayManagerInternal displayManagerInternal = |
| 1154 | LocalServices.getService(DisplayManagerInternal.class); |
| 1155 | return displayManagerInternal.setDisplayedContentSamplingEnabled( |
| 1156 | Display.DEFAULT_DISPLAY, enable, COLOR_SAMPLE_COMPONENT_MASK, noFrames); |
| 1157 | } |
| 1158 | |
| 1159 | public void registerDisplayListener(Context context, |
| 1160 | DisplayManager.DisplayListener listener, Handler handler) { |
| 1161 | final DisplayManager displayManager = context.getSystemService(DisplayManager.class); |
| 1162 | displayManager.registerDisplayListener(listener, handler); |
| 1163 | } |
| 1164 | |
| 1165 | public void unRegisterDisplayListener(Context context, |
| 1166 | DisplayManager.DisplayListener listener) { |
| 1167 | final DisplayManager displayManager = context.getSystemService(DisplayManager.class); |
| 1168 | displayManager.unregisterDisplayListener(listener); |
| 1169 | } |
Kenny Guy | 22bd044 | 2017-10-26 00:15:54 +0100 | [diff] [blame] | 1170 | } |
| 1171 | } |