PageRenderTime 74ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/services/core/java/com/android/server/UiModeManagerService.java

https://gitlab.com/AvayKumar/android_frameworks_base
Java | 636 lines | 509 code | 73 blank | 54 comment | 121 complexity | 301a8acf11aab5c730b3f0d6f50a98af MD5 | raw file
  1. /*
  2. * Copyright (C) 2008 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.server;
  17. import android.app.Activity;
  18. import android.app.ActivityManager;
  19. import android.app.ActivityManagerNative;
  20. import android.app.IUiModeManager;
  21. import android.app.Notification;
  22. import android.app.NotificationManager;
  23. import android.app.PendingIntent;
  24. import android.app.StatusBarManager;
  25. import android.app.UiModeManager;
  26. import android.content.BroadcastReceiver;
  27. import android.content.Context;
  28. import android.content.Intent;
  29. import android.content.IntentFilter;
  30. import android.content.pm.PackageManager;
  31. import android.content.res.Configuration;
  32. import android.os.BatteryManager;
  33. import android.os.Binder;
  34. import android.os.Handler;
  35. import android.os.IBinder;
  36. import android.os.PowerManager;
  37. import android.os.RemoteException;
  38. import android.os.UserHandle;
  39. import android.provider.Settings;
  40. import android.service.dreams.Sandman;
  41. import android.util.Slog;
  42. import java.io.FileDescriptor;
  43. import java.io.PrintWriter;
  44. import com.android.internal.R;
  45. import com.android.internal.app.DisableCarModeActivity;
  46. import com.android.server.twilight.TwilightListener;
  47. import com.android.server.twilight.TwilightManager;
  48. import com.android.server.twilight.TwilightState;
  49. final class UiModeManagerService extends SystemService {
  50. private static final String TAG = UiModeManager.class.getSimpleName();
  51. private static final boolean LOG = false;
  52. // Enable launching of applications when entering the dock.
  53. private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
  54. private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
  55. final Object mLock = new Object();
  56. private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
  57. private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
  58. int mNightMode = UiModeManager.MODE_NIGHT_NO;
  59. private boolean mCarModeEnabled = false;
  60. private boolean mCharging = false;
  61. private int mDefaultUiModeType;
  62. private boolean mCarModeKeepsScreenOn;
  63. private boolean mDeskModeKeepsScreenOn;
  64. private boolean mTelevision;
  65. private boolean mWatch;
  66. private boolean mComputedNightMode;
  67. private int mCarModeEnableFlags;
  68. int mCurUiMode = 0;
  69. private int mSetUiMode = 0;
  70. private boolean mHoldingConfiguration = false;
  71. private Configuration mConfiguration = new Configuration();
  72. boolean mSystemReady;
  73. private final Handler mHandler = new Handler();
  74. private TwilightManager mTwilightManager;
  75. private NotificationManager mNotificationManager;
  76. private StatusBarManager mStatusBarManager;
  77. private PowerManager.WakeLock mWakeLock;
  78. public UiModeManagerService(Context context) {
  79. super(context);
  80. }
  81. private static Intent buildHomeIntent(String category) {
  82. Intent intent = new Intent(Intent.ACTION_MAIN);
  83. intent.addCategory(category);
  84. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
  85. | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
  86. return intent;
  87. }
  88. // The broadcast receiver which receives the result of the ordered broadcast sent when
  89. // the dock state changes. The original ordered broadcast is sent with an initial result
  90. // code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g.,
  91. // to RESULT_CANCELED, then the intent to start a dock app will not be sent.
  92. private final BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
  93. @Override
  94. public void onReceive(Context context, Intent intent) {
  95. if (getResultCode() != Activity.RESULT_OK) {
  96. if (LOG) {
  97. Slog.v(TAG, "Handling broadcast result for action " + intent.getAction()
  98. + ": canceled: " + getResultCode());
  99. }
  100. return;
  101. }
  102. final int enableFlags = intent.getIntExtra("enableFlags", 0);
  103. final int disableFlags = intent.getIntExtra("disableFlags", 0);
  104. synchronized (mLock) {
  105. updateAfterBroadcastLocked(intent.getAction(), enableFlags, disableFlags);
  106. }
  107. }
  108. };
  109. private final BroadcastReceiver mDockModeReceiver = new BroadcastReceiver() {
  110. @Override
  111. public void onReceive(Context context, Intent intent) {
  112. int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
  113. Intent.EXTRA_DOCK_STATE_UNDOCKED);
  114. updateDockState(state);
  115. }
  116. };
  117. private final BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
  118. @Override
  119. public void onReceive(Context context, Intent intent) {
  120. mCharging = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
  121. synchronized (mLock) {
  122. if (mSystemReady) {
  123. updateLocked(0, 0);
  124. }
  125. }
  126. }
  127. };
  128. private final TwilightListener mTwilightListener = new TwilightListener() {
  129. @Override
  130. public void onTwilightStateChanged() {
  131. updateTwilight();
  132. }
  133. };
  134. @Override
  135. public void onStart() {
  136. final Context context = getContext();
  137. mTwilightManager = getLocalService(TwilightManager.class);
  138. final PowerManager powerManager =
  139. (PowerManager) context.getSystemService(Context.POWER_SERVICE);
  140. mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
  141. context.registerReceiver(mDockModeReceiver,
  142. new IntentFilter(Intent.ACTION_DOCK_EVENT));
  143. context.registerReceiver(mBatteryReceiver,
  144. new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
  145. mConfiguration.setToDefaults();
  146. mDefaultUiModeType = context.getResources().getInteger(
  147. com.android.internal.R.integer.config_defaultUiModeType);
  148. mCarModeKeepsScreenOn = (context.getResources().getInteger(
  149. com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
  150. mDeskModeKeepsScreenOn = (context.getResources().getInteger(
  151. com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
  152. mTelevision = context.getPackageManager().hasSystemFeature(
  153. PackageManager.FEATURE_TELEVISION) ||
  154. context.getPackageManager().hasSystemFeature(
  155. PackageManager.FEATURE_LEANBACK);
  156. mWatch = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
  157. mNightMode = Settings.Secure.getInt(context.getContentResolver(),
  158. Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
  159. mTwilightManager.registerListener(mTwilightListener, mHandler);
  160. publishBinderService(Context.UI_MODE_SERVICE, mService);
  161. }
  162. private final IBinder mService = new IUiModeManager.Stub() {
  163. @Override
  164. public void enableCarMode(int flags) {
  165. final long ident = Binder.clearCallingIdentity();
  166. try {
  167. synchronized (mLock) {
  168. setCarModeLocked(true, flags);
  169. if (mSystemReady) {
  170. updateLocked(flags, 0);
  171. }
  172. }
  173. } finally {
  174. Binder.restoreCallingIdentity(ident);
  175. }
  176. }
  177. @Override
  178. public void disableCarMode(int flags) {
  179. final long ident = Binder.clearCallingIdentity();
  180. try {
  181. synchronized (mLock) {
  182. setCarModeLocked(false, 0);
  183. if (mSystemReady) {
  184. updateLocked(0, flags);
  185. }
  186. }
  187. } finally {
  188. Binder.restoreCallingIdentity(ident);
  189. }
  190. }
  191. @Override
  192. public int getCurrentModeType() {
  193. final long ident = Binder.clearCallingIdentity();
  194. try {
  195. synchronized (mLock) {
  196. return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
  197. }
  198. } finally {
  199. Binder.restoreCallingIdentity(ident);
  200. }
  201. }
  202. @Override
  203. public void setNightMode(int mode) {
  204. switch (mode) {
  205. case UiModeManager.MODE_NIGHT_NO:
  206. case UiModeManager.MODE_NIGHT_YES:
  207. case UiModeManager.MODE_NIGHT_AUTO:
  208. break;
  209. default:
  210. throw new IllegalArgumentException("Unknown mode: " + mode);
  211. }
  212. final long ident = Binder.clearCallingIdentity();
  213. try {
  214. synchronized (mLock) {
  215. if (isDoingNightModeLocked() && mNightMode != mode) {
  216. Settings.Secure.putInt(getContext().getContentResolver(),
  217. Settings.Secure.UI_NIGHT_MODE, mode);
  218. mNightMode = mode;
  219. updateLocked(0, 0);
  220. }
  221. }
  222. } finally {
  223. Binder.restoreCallingIdentity(ident);
  224. }
  225. }
  226. @Override
  227. public int getNightMode() {
  228. synchronized (mLock) {
  229. return mNightMode;
  230. }
  231. }
  232. @Override
  233. protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
  234. if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
  235. != PackageManager.PERMISSION_GRANTED) {
  236. pw.println("Permission Denial: can't dump uimode service from from pid="
  237. + Binder.getCallingPid()
  238. + ", uid=" + Binder.getCallingUid());
  239. return;
  240. }
  241. dumpImpl(pw);
  242. }
  243. };
  244. void dumpImpl(PrintWriter pw) {
  245. synchronized (mLock) {
  246. pw.println("Current UI Mode Service state:");
  247. pw.print(" mDockState="); pw.print(mDockState);
  248. pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
  249. pw.print(" mNightMode="); pw.print(mNightMode);
  250. pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
  251. pw.print(" mComputedNightMode="); pw.print(mComputedNightMode);
  252. pw.print(" mCarModeEnableFlags="); pw.println(mCarModeEnableFlags);
  253. pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
  254. pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
  255. pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
  256. pw.print(" mSystemReady="); pw.println(mSystemReady);
  257. pw.print(" mTwilightService.getCurrentState()=");
  258. pw.println(mTwilightManager.getCurrentState());
  259. }
  260. }
  261. @Override
  262. public void onBootPhase(int phase) {
  263. if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
  264. synchronized (mLock) {
  265. mSystemReady = true;
  266. mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
  267. updateComputedNightModeLocked();
  268. updateLocked(0, 0);
  269. }
  270. }
  271. }
  272. boolean isDoingNightModeLocked() {
  273. return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
  274. }
  275. void setCarModeLocked(boolean enabled, int flags) {
  276. if (mCarModeEnabled != enabled) {
  277. mCarModeEnabled = enabled;
  278. }
  279. mCarModeEnableFlags = flags;
  280. }
  281. private void updateDockState(int newState) {
  282. synchronized (mLock) {
  283. if (newState != mDockState) {
  284. mDockState = newState;
  285. setCarModeLocked(mDockState == Intent.EXTRA_DOCK_STATE_CAR, 0);
  286. if (mSystemReady) {
  287. updateLocked(UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME, 0);
  288. }
  289. }
  290. }
  291. }
  292. private static boolean isDeskDockState(int state) {
  293. switch (state) {
  294. case Intent.EXTRA_DOCK_STATE_DESK:
  295. case Intent.EXTRA_DOCK_STATE_LE_DESK:
  296. case Intent.EXTRA_DOCK_STATE_HE_DESK:
  297. return true;
  298. default:
  299. return false;
  300. }
  301. }
  302. private void updateConfigurationLocked() {
  303. int uiMode = mDefaultUiModeType;
  304. if (mTelevision) {
  305. uiMode = Configuration.UI_MODE_TYPE_TELEVISION;
  306. } else if (mWatch) {
  307. uiMode = Configuration.UI_MODE_TYPE_WATCH;
  308. } else if (mCarModeEnabled) {
  309. uiMode = Configuration.UI_MODE_TYPE_CAR;
  310. } else if (isDeskDockState(mDockState)) {
  311. uiMode = Configuration.UI_MODE_TYPE_DESK;
  312. }
  313. if (mCarModeEnabled) {
  314. if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
  315. updateComputedNightModeLocked();
  316. uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
  317. : Configuration.UI_MODE_NIGHT_NO;
  318. } else {
  319. uiMode |= mNightMode << 4;
  320. }
  321. } else {
  322. // Disabling the car mode clears the night mode.
  323. uiMode = (uiMode & ~Configuration.UI_MODE_NIGHT_MASK) | Configuration.UI_MODE_NIGHT_NO;
  324. }
  325. if (LOG) {
  326. Slog.d(TAG,
  327. "updateConfigurationLocked: mDockState=" + mDockState
  328. + "; mCarMode=" + mCarModeEnabled
  329. + "; mNightMode=" + mNightMode
  330. + "; uiMode=" + uiMode);
  331. }
  332. mCurUiMode = uiMode;
  333. if (!mHoldingConfiguration) {
  334. mConfiguration.uiMode = uiMode;
  335. }
  336. }
  337. private void sendConfigurationLocked() {
  338. if (mSetUiMode != mConfiguration.uiMode) {
  339. mSetUiMode = mConfiguration.uiMode;
  340. try {
  341. ActivityManagerNative.getDefault().updateConfiguration(mConfiguration);
  342. } catch (RemoteException e) {
  343. Slog.w(TAG, "Failure communicating with activity manager", e);
  344. }
  345. }
  346. }
  347. void updateLocked(int enableFlags, int disableFlags) {
  348. String action = null;
  349. String oldAction = null;
  350. if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
  351. adjustStatusBarCarModeLocked();
  352. oldAction = UiModeManager.ACTION_EXIT_CAR_MODE;
  353. } else if (isDeskDockState(mLastBroadcastState)) {
  354. oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
  355. }
  356. if (mCarModeEnabled) {
  357. if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_CAR) {
  358. adjustStatusBarCarModeLocked();
  359. if (oldAction != null) {
  360. getContext().sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
  361. }
  362. mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
  363. action = UiModeManager.ACTION_ENTER_CAR_MODE;
  364. }
  365. } else if (isDeskDockState(mDockState)) {
  366. if (!isDeskDockState(mLastBroadcastState)) {
  367. if (oldAction != null) {
  368. getContext().sendBroadcastAsUser(new Intent(oldAction), UserHandle.ALL);
  369. }
  370. mLastBroadcastState = mDockState;
  371. action = UiModeManager.ACTION_ENTER_DESK_MODE;
  372. }
  373. } else {
  374. mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
  375. action = oldAction;
  376. }
  377. if (action != null) {
  378. if (LOG) {
  379. Slog.v(TAG, String.format(
  380. "updateLocked: preparing broadcast: action=%s enable=0x%08x disable=0x%08x",
  381. action, enableFlags, disableFlags));
  382. }
  383. // Send the ordered broadcast; the result receiver will receive after all
  384. // broadcasts have been sent. If any broadcast receiver changes the result
  385. // code from the initial value of RESULT_OK, then the result receiver will
  386. // not launch the corresponding dock application. This gives apps a chance
  387. // to override the behavior and stay in their app even when the device is
  388. // placed into a dock.
  389. Intent intent = new Intent(action);
  390. intent.putExtra("enableFlags", enableFlags);
  391. intent.putExtra("disableFlags", disableFlags);
  392. getContext().sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
  393. mResultReceiver, null, Activity.RESULT_OK, null, null);
  394. // Attempting to make this transition a little more clean, we are going
  395. // to hold off on doing a configuration change until we have finished
  396. // the broadcast and started the home activity.
  397. mHoldingConfiguration = true;
  398. updateConfigurationLocked();
  399. } else {
  400. String category = null;
  401. if (mCarModeEnabled) {
  402. if (ENABLE_LAUNCH_CAR_DOCK_APP
  403. && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
  404. category = Intent.CATEGORY_CAR_DOCK;
  405. }
  406. } else if (isDeskDockState(mDockState)) {
  407. if (ENABLE_LAUNCH_DESK_DOCK_APP
  408. && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
  409. category = Intent.CATEGORY_DESK_DOCK;
  410. }
  411. } else {
  412. if ((disableFlags & UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
  413. category = Intent.CATEGORY_HOME;
  414. }
  415. }
  416. if (LOG) {
  417. Slog.v(TAG, "updateLocked: null action, mDockState="
  418. + mDockState +", category=" + category);
  419. }
  420. sendConfigurationAndStartDreamOrDockAppLocked(category);
  421. }
  422. // keep screen on when charging and in car mode
  423. boolean keepScreenOn = mCharging &&
  424. ((mCarModeEnabled && mCarModeKeepsScreenOn &&
  425. (mCarModeEnableFlags & UiModeManager.ENABLE_CAR_MODE_ALLOW_SLEEP) == 0) ||
  426. (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
  427. if (keepScreenOn != mWakeLock.isHeld()) {
  428. if (keepScreenOn) {
  429. mWakeLock.acquire();
  430. } else {
  431. mWakeLock.release();
  432. }
  433. }
  434. }
  435. private void updateAfterBroadcastLocked(String action, int enableFlags, int disableFlags) {
  436. // Launch a dock activity
  437. String category = null;
  438. if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(action)) {
  439. // Only launch car home when car mode is enabled and the caller
  440. // has asked us to switch to it.
  441. if (ENABLE_LAUNCH_CAR_DOCK_APP
  442. && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
  443. category = Intent.CATEGORY_CAR_DOCK;
  444. }
  445. } else if (UiModeManager.ACTION_ENTER_DESK_MODE.equals(action)) {
  446. // Only launch car home when desk mode is enabled and the caller
  447. // has asked us to switch to it. Currently re-using the car
  448. // mode flag since we don't have a formal API for "desk mode".
  449. if (ENABLE_LAUNCH_DESK_DOCK_APP
  450. && (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
  451. category = Intent.CATEGORY_DESK_DOCK;
  452. }
  453. } else {
  454. // Launch the standard home app if requested.
  455. if ((disableFlags & UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
  456. category = Intent.CATEGORY_HOME;
  457. }
  458. }
  459. if (LOG) {
  460. Slog.v(TAG, String.format(
  461. "Handling broadcast result for action %s: enable=0x%08x, disable=0x%08x, "
  462. + "category=%s",
  463. action, enableFlags, disableFlags, category));
  464. }
  465. sendConfigurationAndStartDreamOrDockAppLocked(category);
  466. }
  467. private void sendConfigurationAndStartDreamOrDockAppLocked(String category) {
  468. // Update the configuration but don't send it yet.
  469. mHoldingConfiguration = false;
  470. updateConfigurationLocked();
  471. // Start the dock app, if there is one.
  472. boolean dockAppStarted = false;
  473. if (category != null) {
  474. // Now we are going to be careful about switching the
  475. // configuration and starting the activity -- we need to
  476. // do this in a specific order under control of the
  477. // activity manager, to do it cleanly. So compute the
  478. // new config, but don't set it yet, and let the
  479. // activity manager take care of both the start and config
  480. // change.
  481. Intent homeIntent = buildHomeIntent(category);
  482. if (Sandman.shouldStartDockApp(getContext(), homeIntent)) {
  483. try {
  484. int result = ActivityManagerNative.getDefault().startActivityWithConfig(
  485. null, null, homeIntent, null, null, null, 0, 0,
  486. mConfiguration, null, UserHandle.USER_CURRENT);
  487. if (result >= ActivityManager.START_SUCCESS) {
  488. dockAppStarted = true;
  489. } else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
  490. Slog.e(TAG, "Could not start dock app: " + homeIntent
  491. + ", startActivityWithConfig result " + result);
  492. }
  493. } catch (RemoteException ex) {
  494. Slog.e(TAG, "Could not start dock app: " + homeIntent, ex);
  495. }
  496. }
  497. }
  498. // Send the new configuration.
  499. sendConfigurationLocked();
  500. // If we did not start a dock app, then start dreaming if supported.
  501. if (category != null && !dockAppStarted) {
  502. Sandman.startDreamWhenDockedIfAppropriate(getContext());
  503. }
  504. }
  505. private void adjustStatusBarCarModeLocked() {
  506. final Context context = getContext();
  507. if (mStatusBarManager == null) {
  508. mStatusBarManager = (StatusBarManager)
  509. context.getSystemService(Context.STATUS_BAR_SERVICE);
  510. }
  511. // Fear not: StatusBarManagerService manages a list of requests to disable
  512. // features of the status bar; these are ORed together to form the
  513. // active disabled list. So if (for example) the device is locked and
  514. // the status bar should be totally disabled, the calls below will
  515. // have no effect until the device is unlocked.
  516. if (mStatusBarManager != null) {
  517. mStatusBarManager.disable(mCarModeEnabled
  518. ? StatusBarManager.DISABLE_NOTIFICATION_TICKER
  519. : StatusBarManager.DISABLE_NONE);
  520. }
  521. if (mNotificationManager == null) {
  522. mNotificationManager = (NotificationManager)
  523. context.getSystemService(Context.NOTIFICATION_SERVICE);
  524. }
  525. if (mNotificationManager != null) {
  526. if (mCarModeEnabled) {
  527. Intent carModeOffIntent = new Intent(context, DisableCarModeActivity.class);
  528. Notification n = new Notification();
  529. n.icon = R.drawable.stat_notify_car_mode;
  530. n.defaults = Notification.DEFAULT_LIGHTS;
  531. n.flags = Notification.FLAG_ONGOING_EVENT;
  532. n.when = 0;
  533. n.color = context.getResources().getColor(
  534. com.android.internal.R.color.system_notification_accent_color);
  535. n.setLatestEventInfo(
  536. context,
  537. context.getString(R.string.car_mode_disable_notification_title),
  538. context.getString(R.string.car_mode_disable_notification_message),
  539. PendingIntent.getActivityAsUser(context, 0, carModeOffIntent, 0,
  540. null, UserHandle.CURRENT));
  541. mNotificationManager.notifyAsUser(null,
  542. R.string.car_mode_disable_notification_title, n, UserHandle.ALL);
  543. } else {
  544. mNotificationManager.cancelAsUser(null,
  545. R.string.car_mode_disable_notification_title, UserHandle.ALL);
  546. }
  547. }
  548. }
  549. void updateTwilight() {
  550. synchronized (mLock) {
  551. if (isDoingNightModeLocked() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
  552. updateComputedNightModeLocked();
  553. updateLocked(0, 0);
  554. }
  555. }
  556. }
  557. private void updateComputedNightModeLocked() {
  558. TwilightState state = mTwilightManager.getCurrentState();
  559. if (state != null) {
  560. mComputedNightMode = state.isNight();
  561. }
  562. }
  563. }