Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2015 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 | package com.android.car; |
| 17 | |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 18 | import android.car.CarApiUtil; |
| 19 | import android.car.settings.CarSettings; |
| 20 | import android.car.settings.GarageModeSettingsObserver; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 21 | import android.content.Context; |
| 22 | import android.content.SharedPreferences; |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 23 | import android.net.Uri; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 24 | import android.os.Handler; |
| 25 | import android.os.IDeviceIdleController; |
| 26 | import android.os.IMaintenanceActivityListener; |
| 27 | import android.os.Message; |
| 28 | import android.os.RemoteException; |
| 29 | import android.os.ServiceManager; |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 30 | import android.preference.PreferenceManager; |
| 31 | import android.provider.Settings; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 32 | import android.util.Log; |
| 33 | |
| 34 | import com.android.internal.annotations.GuardedBy; |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 35 | import com.android.internal.annotations.VisibleForTesting; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 36 | |
| 37 | import java.io.PrintWriter; |
| 38 | import java.util.Calendar; |
| 39 | |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 40 | import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_ENABLED_URI; |
| 41 | import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_MAINTENANCE_WINDOW_URI; |
| 42 | import static android.car.settings.GarageModeSettingsObserver.GARAGE_MODE_WAKE_UP_TIME_URI; |
| 43 | |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 44 | /** |
| 45 | * Controls car garage mode. |
| 46 | * |
| 47 | * Car garage mode is a time window for the car to do maintenance work when the car is not in use. |
| 48 | * The {@link com.android.car.GarageModeService} interacts with {@link com.android.car.CarPowerManagementService} |
| 49 | * to start and end garage mode. A {@link com.android.car.GarageModeService.GarageModePolicy} defines |
| 50 | * when the garage mode should start and how long it should last. |
| 51 | */ |
| 52 | public class GarageModeService implements CarServiceBase, |
| 53 | CarPowerManagementService.PowerEventProcessingHandler, |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 54 | CarPowerManagementService.PowerServiceEventListener, |
| 55 | DeviceIdleControllerWrapper.DeviceMaintenanceActivityListener { |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 56 | private static String TAG = "GarageModeService"; |
Vitalii Tomkiv | 1b1247b | 2016-09-30 11:27:19 -0700 | [diff] [blame] | 57 | private static final boolean DBG = false; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 58 | |
| 59 | private static final int MSG_EXIT_GARAGE_MODE_EARLY = 0; |
| 60 | private static final int MSG_WRITE_TO_PREF = 1; |
| 61 | |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 62 | private static final String KEY_GARAGE_MODE_INDEX = "garage_mode_index"; |
| 63 | |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 64 | // wait for 10 seconds to allow maintenance activities to start (e.g., connecting to wifi). |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 65 | protected static final int MAINTENANCE_ACTIVITY_START_GRACE_PERIOUD = 10 * 1000; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 66 | |
| 67 | private final CarPowerManagementService mPowerManagementService; |
| 68 | protected final Context mContext; |
| 69 | |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 70 | @VisibleForTesting |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 71 | @GuardedBy("this") |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 72 | protected boolean mInGarageMode; |
| 73 | @VisibleForTesting |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 74 | @GuardedBy("this") |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 75 | protected boolean mMaintenanceActive; |
| 76 | @VisibleForTesting |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 77 | @GuardedBy("this") |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 78 | protected int mGarageModeIndex; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 79 | |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 80 | @GuardedBy("this") |
| 81 | @VisibleForTesting |
| 82 | protected int mMaintenanceWindow; |
| 83 | @GuardedBy("this") |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 84 | private GarageModePolicy mPolicy; |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 85 | @GuardedBy("this") |
| 86 | private int mWakeUpHour = 0; |
| 87 | @GuardedBy("this") |
| 88 | private int mWakeUpMin = 0; |
| 89 | @GuardedBy("this") |
| 90 | private boolean mGarageModeEnabled; |
| 91 | |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 92 | |
| 93 | private SharedPreferences mSharedPreferences; |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 94 | private final GarageModeSettingsObserver mContentObserver; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 95 | |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 96 | private DeviceIdleControllerWrapper mDeviceIdleController; |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 97 | private final GarageModeHandler mHandler = new GarageModeHandler(); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 98 | |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 99 | private class GarageModeHandler extends Handler { |
| 100 | @Override |
| 101 | public void handleMessage(Message msg) { |
| 102 | switch (msg.what) { |
| 103 | case MSG_EXIT_GARAGE_MODE_EARLY: |
| 104 | mPowerManagementService.notifyPowerEventProcessingCompletion( |
| 105 | GarageModeService.this); |
| 106 | break; |
| 107 | case MSG_WRITE_TO_PREF: |
| 108 | writeToPref(msg.arg1); |
| 109 | break; |
| 110 | } |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | public GarageModeService(Context context, CarPowerManagementService powerManagementService) { |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 115 | this(context, powerManagementService, null); |
| 116 | } |
| 117 | |
| 118 | @VisibleForTesting |
| 119 | protected GarageModeService(Context context, CarPowerManagementService powerManagementService, |
| 120 | DeviceIdleControllerWrapper deviceIdleController) { |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 121 | mContext = context; |
| 122 | mPowerManagementService = powerManagementService; |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 123 | if (deviceIdleController == null) { |
| 124 | mDeviceIdleController = new DefaultDeviceIdleController(); |
| 125 | } else { |
| 126 | mDeviceIdleController = deviceIdleController; |
| 127 | } |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 128 | mContentObserver = new GarageModeSettingsObserver(mContext, mHandler) { |
| 129 | @Override |
| 130 | public void onChange(boolean selfChange, Uri uri) { |
| 131 | onSettingsChangedInternal(uri); |
| 132 | } |
| 133 | }; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 134 | } |
| 135 | |
| 136 | @Override |
| 137 | public void init() { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 138 | logd("init GarageMode"); |
Yao Chen | 96fd18b | 2017-03-22 13:16:31 -0700 | [diff] [blame] | 139 | mSharedPreferences = PreferenceManager.getDefaultSharedPreferences( |
| 140 | mContext.createDeviceProtectedStorageContext()); |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 141 | final int index = mSharedPreferences.getInt(KEY_GARAGE_MODE_INDEX, 0); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 142 | synchronized (this) { |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 143 | mMaintenanceActive = mDeviceIdleController.startTracking(this); |
| 144 | mGarageModeIndex = index; |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 145 | readPolicyLocked(); |
| 146 | readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW, |
| 147 | CarSettings.Global.KEY_GARAGE_MODE_ENABLED, |
| 148 | CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 149 | } |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 150 | mContentObserver.register(); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 151 | mPowerManagementService.registerPowerEventProcessingHandler(this); |
| 152 | } |
| 153 | |
| 154 | @Override |
| 155 | public void release() { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 156 | logd("release GarageModeService"); |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 157 | mDeviceIdleController.stopTracking(); |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 158 | mContentObserver.unregister(); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 159 | } |
| 160 | |
| 161 | @Override |
| 162 | public void dump(PrintWriter writer) { |
| 163 | writer.println("mGarageModeIndex: " + mGarageModeIndex); |
| 164 | writer.println("inGarageMode? " + mInGarageMode); |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 165 | writer.println("GarageModeTime: " + mWakeUpHour + ":" + mWakeUpMin); |
| 166 | writer.println("GarageModeEnabled " + mGarageModeEnabled); |
| 167 | writer.println("GarageModeTimeWindow " + mMaintenanceWindow + " ms"); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 168 | } |
| 169 | |
| 170 | @Override |
| 171 | public long onPrepareShutdown(boolean shuttingDown) { |
| 172 | // this is the beginning of each garage mode. |
| 173 | synchronized (this) { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 174 | logd("onPrePowerEvent " + shuttingDown); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 175 | mInGarageMode = true; |
| 176 | mGarageModeIndex++; |
| 177 | mHandler.removeMessages(MSG_EXIT_GARAGE_MODE_EARLY); |
| 178 | if (!mMaintenanceActive) { |
| 179 | mHandler.sendMessageDelayed( |
| 180 | mHandler.obtainMessage(MSG_EXIT_GARAGE_MODE_EARLY), |
| 181 | MAINTENANCE_ACTIVITY_START_GRACE_PERIOUD); |
| 182 | } |
| 183 | // We always reserve the maintenance window first. If later, we found no |
| 184 | // maintenance work active, we will exit garage mode early after |
| 185 | // MAINTENANCE_ACTIVITY_START_GRACE_PERIOUD |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 186 | return mMaintenanceWindow; |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 187 | } |
| 188 | } |
| 189 | |
| 190 | @Override |
| 191 | public void onPowerOn(boolean displayOn) { |
| 192 | synchronized (this) { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 193 | logd("onPowerOn: " + displayOn); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 194 | if (displayOn) { |
| 195 | // the car is use now. reset the garage mode counter. |
| 196 | mGarageModeIndex = 0; |
| 197 | } |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | @Override |
| 202 | public int getWakeupTime() { |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 203 | synchronized (this) { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 204 | if (!mGarageModeEnabled) { |
| 205 | return 0; |
| 206 | } |
| 207 | return mPolicy.getNextWakeUpTime(mGarageModeIndex, mWakeUpHour, mWakeUpMin); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 208 | } |
| 209 | } |
| 210 | |
| 211 | @Override |
| 212 | public void onSleepExit() { |
| 213 | // ignored |
| 214 | } |
| 215 | |
| 216 | @Override |
| 217 | public void onSleepEntry() { |
| 218 | synchronized (this) { |
| 219 | mInGarageMode = false; |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | @Override |
| 224 | public void onShutdown() { |
| 225 | synchronized (this) { |
| 226 | mHandler.sendMessage( |
| 227 | mHandler.obtainMessage(MSG_WRITE_TO_PREF, mGarageModeIndex, 0)); |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | private void readPolicyLocked() { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 232 | logd("readPolicy"); |
Keun-young Park | f921520 | 2016-10-10 12:34:08 -0700 | [diff] [blame] | 233 | // TODO: define a xml schema for policy and read it from system dir. bug: 32096969 |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 234 | mPolicy = new DefaultGarageModePolicy(); |
| 235 | } |
| 236 | |
| 237 | private void writeToPref(int index) { |
| 238 | SharedPreferences.Editor editor = mSharedPreferences.edit(); |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 239 | editor.putInt(KEY_GARAGE_MODE_INDEX, index); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 240 | editor.commit(); |
| 241 | } |
| 242 | |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 243 | @Override |
| 244 | public void onMaintenanceActivityChanged(boolean active) { |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 245 | boolean shouldReportCompletion = false; |
| 246 | synchronized (this) { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 247 | logd("onMaintenanceActivityChanged: " + active); |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 248 | mMaintenanceActive = active; |
| 249 | if (!mInGarageMode) { |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 250 | return; |
| 251 | } |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 252 | |
| 253 | if (!active) { |
| 254 | shouldReportCompletion = true; |
| 255 | mInGarageMode = false; |
| 256 | } else { |
| 257 | // we are in garage mode, and maintenance work has just begun. |
| 258 | mHandler.removeMessages(MSG_EXIT_GARAGE_MODE_EARLY); |
| 259 | } |
| 260 | } |
| 261 | if (shouldReportCompletion) { |
| 262 | // we are in garage mode, and maintenance work has finished. |
| 263 | mPowerManagementService.notifyPowerEventProcessingCompletion(this); |
| 264 | } |
| 265 | } |
| 266 | |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 267 | public abstract static class GarageModePolicy { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 268 | abstract public int getNextWakeUpTime(int index, int hour, int min); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 269 | /** |
| 270 | * Returns number of seconds between now to 1am {@param numDays} days later. |
| 271 | */ |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 272 | public static int nextWakeUpSeconds(int numDays, int hour, int min) { |
Keun-young Park | f921520 | 2016-10-10 12:34:08 -0700 | [diff] [blame] | 273 | // TODO: Should select a random time within a window. bug: 32096386 |
| 274 | // This is to avoid all cars update at the same time. |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 275 | Calendar next = Calendar.getInstance(); |
| 276 | next.add(Calendar.DATE, numDays); |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 277 | next.set(Calendar.HOUR_OF_DAY, hour); |
| 278 | next.set(Calendar.MINUTE, min); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 279 | next.set(Calendar.SECOND, 0); |
| 280 | |
| 281 | Calendar now = Calendar.getInstance(); |
| 282 | return (next.get(Calendar.MILLISECOND) - now.get(Calendar.MILLISECOND)) / 1000; |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | /** |
| 287 | * Default garage mode policy. |
| 288 | * |
| 289 | * The first wake up time is set to be 1am the next day. And it keeps waking up every day for a |
| 290 | * week. After that, wake up every 7 days for a month, and wake up every 30 days thereafter. |
| 291 | */ |
| 292 | private static class DefaultGarageModePolicy extends GarageModePolicy { |
| 293 | private static final int COL_INDEX = 0; |
| 294 | private static final int COL_WAKEUP_TIME = 1; |
| 295 | |
| 296 | private static final int[][] WAKE_UP_TIME = new int[][] { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 297 | {7 /*index <= 7*/, 1 /* wake up the next day */}, |
| 298 | {11 /* 7 < index <= 11 */, 7 /* wake up the next week */}, |
| 299 | {Integer.MAX_VALUE /* index > 11 */, 30 /* wake up the next month */} |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 300 | }; |
| 301 | |
| 302 | @Override |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 303 | public int getNextWakeUpTime(int index, int hour, int min) { |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 304 | for (int i = 0; i < WAKE_UP_TIME.length; i++) { |
| 305 | if (index <= WAKE_UP_TIME[i][COL_INDEX]) { |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 306 | return nextWakeUpSeconds(WAKE_UP_TIME[i][COL_WAKEUP_TIME], hour, min); |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 307 | } |
| 308 | } |
| 309 | |
| 310 | Log.w(TAG, "Integer.MAX number of wake ups... How long have we been sleeping? "); |
| 311 | return 0; |
| 312 | } |
| 313 | } |
Yao Chen | dacd724 | 2016-01-26 14:42:42 -0800 | [diff] [blame] | 314 | |
| 315 | private static class DefaultDeviceIdleController extends DeviceIdleControllerWrapper { |
| 316 | private IDeviceIdleController mDeviceIdleController; |
| 317 | private MaintenanceActivityListener mMaintenanceActivityListener |
| 318 | = new MaintenanceActivityListener(); |
| 319 | |
| 320 | @Override |
| 321 | public boolean startLocked() { |
| 322 | mDeviceIdleController = IDeviceIdleController.Stub.asInterface( |
| 323 | ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); |
| 324 | boolean active = false; |
| 325 | try { |
| 326 | active = mDeviceIdleController |
| 327 | .registerMaintenanceActivityListener(mMaintenanceActivityListener); |
| 328 | } catch (RemoteException e) { |
| 329 | Log.e(TAG, "Unable to register listener with DeviceIdleController", e); |
| 330 | } |
| 331 | return active; |
| 332 | } |
| 333 | |
| 334 | @Override |
| 335 | public void stopTracking() { |
| 336 | try { |
| 337 | if (mDeviceIdleController != null) { |
| 338 | mDeviceIdleController.unregisterMaintenanceActivityListener( |
| 339 | mMaintenanceActivityListener); |
| 340 | } |
| 341 | } catch (RemoteException e) { |
| 342 | Log.e(TAG, "Fail to unregister listener.", e); |
| 343 | } |
| 344 | } |
| 345 | |
| 346 | private final class MaintenanceActivityListener extends IMaintenanceActivityListener.Stub { |
| 347 | @Override |
| 348 | public void onMaintenanceActivityChanged(final boolean active) { |
| 349 | DefaultDeviceIdleController.this.setMaintenanceActivity(active); |
| 350 | } |
| 351 | } |
| 352 | } |
Yao Chen | 94d4766 | 2016-07-28 14:03:28 -0700 | [diff] [blame] | 353 | |
| 354 | private void logd(String msg) { |
| 355 | if (DBG) { |
| 356 | Log.d(TAG, msg); |
| 357 | } |
| 358 | } |
| 359 | |
| 360 | private void readFromSettingsLocked(String... keys) { |
| 361 | for (String key : keys) { |
| 362 | switch (key) { |
| 363 | case CarSettings.Global.KEY_GARAGE_MODE_ENABLED: |
| 364 | mGarageModeEnabled = |
| 365 | Settings.Global.getInt(mContext.getContentResolver(), key, 1) == 1; |
| 366 | break; |
| 367 | case CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME: |
| 368 | int time[] = CarApiUtil.decodeGarageTimeSetting( |
| 369 | Settings.Global.getString(mContext.getContentResolver(), |
| 370 | CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME)); |
| 371 | mWakeUpHour = time[0]; |
| 372 | mWakeUpMin = time[1]; |
| 373 | break; |
| 374 | case CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW: |
| 375 | mMaintenanceWindow = Settings.Global.getInt( |
| 376 | mContext.getContentResolver(), key, |
| 377 | CarSettings.DEFAULT_GARAGE_MODE_MAINTENANCE_WINDOW); |
| 378 | break; |
| 379 | default: |
| 380 | Log.e(TAG, "Unknown setting key " + key); |
| 381 | } |
| 382 | } |
| 383 | } |
| 384 | |
| 385 | private void onSettingsChangedInternal(Uri uri) { |
| 386 | synchronized (this) { |
| 387 | logd("Content Observer onChange: " + uri); |
| 388 | if (uri.equals(GARAGE_MODE_ENABLED_URI)) { |
| 389 | readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_ENABLED); |
| 390 | } else if (uri.equals(GARAGE_MODE_WAKE_UP_TIME_URI)) { |
| 391 | readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_WAKE_UP_TIME); |
| 392 | } else if (uri.equals(GARAGE_MODE_MAINTENANCE_WINDOW_URI)) { |
| 393 | readFromSettingsLocked(CarSettings.Global.KEY_GARAGE_MODE_MAINTENANCE_WINDOW); |
| 394 | } |
| 395 | logd(String.format( |
| 396 | "onSettingsChanged %s. enabled: %s, wakeUpTime: %d:%d, windowSize: %d", |
| 397 | uri, mGarageModeEnabled, mWakeUpHour, mWakeUpMin, mMaintenanceWindow)); |
| 398 | } |
| 399 | } |
Yao Chen | 3a7976d | 2016-01-20 17:27:08 -0800 | [diff] [blame] | 400 | } |