UiModeManagerService.java revision 9c9c532d3625ba2485eb4ea6924ed0a0163fd958
17299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn/*
27299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * Copyright (C) 2008 The Android Open Source Project
37299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn *
47299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
57299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * you may not use this file except in compliance with the License.
67299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * You may obtain a copy of the License at
77299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn *
87299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
97299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn *
107299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
117299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
127299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * See the License for the specific language governing permissions and
147299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn * limitations under the License.
157299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn */
167299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
177299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornpackage com.android.server;
187299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
197299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.Activity;
207299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.ActivityManagerNative;
217299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.AlarmManager;
227299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.IUiModeManager;
237299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.Notification;
247299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.NotificationManager;
257299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.PendingIntent;
267299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.StatusBarManager;
277299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.app.UiModeManager;
287299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.content.BroadcastReceiver;
297299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.content.Context;
307299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.content.Intent;
317299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.content.IntentFilter;
327299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.content.pm.PackageManager;
337299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.content.res.Configuration;
347299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.location.Criteria;
357299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.location.Location;
367299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.location.LocationListener;
377299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.location.LocationManager;
38e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwoodimport android.os.BatteryManager;
397299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.os.Binder;
407299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.os.Bundle;
417299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.os.Handler;
427299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.os.Message;
43e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwoodimport android.os.PowerManager;
447299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.os.RemoteException;
457299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.os.ServiceManager;
462ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackbornimport android.provider.Settings;
477299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.text.format.DateUtils;
487299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.text.format.Time;
497299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport android.util.Slog;
507299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
517299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport java.io.FileDescriptor;
527299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport java.io.PrintWriter;
53ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzheyimport java.util.Iterator;
547299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
557299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport com.android.internal.R;
567299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornimport com.android.internal.app.DisableCarModeActivity;
577299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
587299c41630935a2b106e73e5603579a7747f7535Dianne Hackbornclass UiModeManagerService extends IUiModeManager.Stub {
597299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final String TAG = UiModeManager.class.getSimpleName();
607299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final boolean LOG = false;
617299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
627299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final String KEY_LAST_UPDATE_INTERVAL = "LAST_UPDATE_INTERVAL";
637299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
647299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final int MSG_UPDATE_TWILIGHT = 0;
657299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final int MSG_ENABLE_LOCATION_UPDATES = 1;
667299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
677299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final long LOCATION_UPDATE_MS = 30 * DateUtils.MINUTE_IN_MILLIS;
687299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final float LOCATION_UPDATE_DISTANCE_METER = 1000 * 20;
697299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final long LOCATION_UPDATE_ENABLE_INTERVAL_MIN = 5000;
707299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final long LOCATION_UPDATE_ENABLE_INTERVAL_MAX = 5 * DateUtils.MINUTE_IN_MILLIS;
717299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final double FACTOR_GMT_OFFSET_LONGITUDE = 1000.0 * 360.0 / DateUtils.DAY_IN_MILLIS;
727299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
737299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private static final String ACTION_UPDATE_NIGHT_MODE = "com.android.server.action.UPDATE_NIGHT_MODE";
747299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
757299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private final Context mContext;
767299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
777299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    final Object mLock = new Object();
78ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
797299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
807299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
81ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
827299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private int mNightMode = UiModeManager.MODE_NIGHT_NO;
837299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private boolean mCarModeEnabled = false;
84e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood    private boolean mCharging = false;
85e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood    private final boolean mCarModeKeepsScreenOn;
86e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood    private final boolean mDeskModeKeepsScreenOn;
877299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
887299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private boolean mComputedNightMode;
897299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private int mCurUiMode = 0;
90b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn    private int mSetUiMode = 0;
91ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
92b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn    private boolean mHoldingConfiguration = false;
937299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private Configuration mConfiguration = new Configuration();
94ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
957299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private boolean mSystemReady;
967299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
977299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private NotificationManager mNotificationManager;
987299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
997299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private AlarmManager mAlarmManager;
1007299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
1017299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private LocationManager mLocationManager;
1027299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private Location mLocation;
1037299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private StatusBarManager mStatusBarManager;
104e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood    private final PowerManager.WakeLock mWakeLock;
1057299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
1067299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    // The broadcast receiver which receives the result of the ordered broadcast sent when
1077299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    // the dock state changes. The original ordered broadcast is sent with an initial result
1087299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    // code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g.,
1097299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    // to RESULT_CANCELED, then the intent to start a dock app will not be sent.
1107299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private final BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
1117299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        @Override
1127299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onReceive(Context context, Intent intent) {
1137299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (getResultCode() != Activity.RESULT_OK) {
1147299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                return;
1157299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
1167299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
117b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn            synchronized (mLock) {
118b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                // Launch a dock activity
119b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                String category;
120b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
121b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    // Only launch car home when car mode is enabled.
122b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    category = Intent.CATEGORY_CAR_DOCK;
123b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                } else if (UiModeManager.ACTION_ENTER_DESK_MODE.equals(intent.getAction())) {
124b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    category = Intent.CATEGORY_DESK_DOCK;
125b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                } else {
126b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    category = null;
127b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                }
128b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                if (category != null) {
1292ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // This is the new activity that will serve as home while
1302ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // we are in care mode.
131b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    intent = new Intent(Intent.ACTION_MAIN);
132b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    intent.addCategory(category);
133b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
134b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                            | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1352ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn
1362ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // Now we are going to be careful about switching the
1372ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // configuration and starting the activity -- we need to
1382ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // do this in a specific order under control of the
1392ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // activity manager, to do it cleanly.  So compute the
1402ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // new config, but don't set it yet, and let the
1412ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // activity manager take care of both the start and config
1422ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    // change.
1432ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    Configuration newConfig = null;
1442ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    if (mHoldingConfiguration) {
145d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                        mHoldingConfiguration = false;
1462ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                        updateConfigurationLocked(false);
1472ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                        newConfig = mConfiguration;
1482ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    }
149b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    try {
1502ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                        ActivityManagerNative.getDefault().startActivityWithConfig(
1512ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                                null, intent, null, null, 0, null, null, 0, false, false,
1522ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                                newConfig);
1532ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                        mHoldingConfiguration = false;
1542ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    } catch (RemoteException e) {
155b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                        Slog.w(TAG, e.getCause());
156b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    }
157b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                }
158ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
159b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                if (mHoldingConfiguration) {
160b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    mHoldingConfiguration = false;
1612ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    updateConfigurationLocked(true);
1627299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                }
1637299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
1647299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
1657299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    };
1667299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
1677299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private final BroadcastReceiver mTwilightUpdateReceiver = new BroadcastReceiver() {
1687299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        @Override
1697299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onReceive(Context context, Intent intent) {
1707299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (isDoingNightMode() && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
1717299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mHandler.sendEmptyMessage(MSG_UPDATE_TWILIGHT);
1727299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
1737299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
1747299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    };
1757299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
1767299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private final BroadcastReceiver mDockModeReceiver = new BroadcastReceiver() {
1777299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        @Override
1787299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onReceive(Context context, Intent intent) {
1797299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1807299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
1817299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            updateDockState(state);
1827299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
1837299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    };
1847299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
185e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood    private final BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
186e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood        @Override
187e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood        public void onReceive(Context context, Intent intent) {
188e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood            mCharging = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
189e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood            synchronized (mLock) {
190e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                if (mSystemReady) {
191d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                    updateLocked(0);
192e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                }
193e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood            }
194e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood        }
195e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood    };
196e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood
1977299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    // A LocationListener to initialize the network location provider. The location updates
1987299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    // are handled through the passive location provider.
1997299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private final LocationListener mEmptyLocationListener =  new LocationListener() {
2007299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onLocationChanged(Location location) {
2017299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2027299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2037299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onProviderDisabled(String provider) {
2047299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2057299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2067299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onProviderEnabled(String provider) {
2077299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2087299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2097299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onStatusChanged(String provider, int status, Bundle extras) {
2107299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2117299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    };
2127299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2137299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private final LocationListener mLocationListener = new LocationListener() {
2147299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2157299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onLocationChanged(Location location) {
2167299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            final boolean hasMoved = hasMoved(location);
2177299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            final boolean hasBetterAccuracy = mLocation == null
2187299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    || location.getAccuracy() < mLocation.getAccuracy();
2197299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (hasMoved || hasBetterAccuracy) {
2207299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                synchronized (mLock) {
2217299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    mLocation = location;
2227299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    if (hasMoved && isDoingNightMode()
2237299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
2247299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mHandler.sendEmptyMessage(MSG_UPDATE_TWILIGHT);
2257299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
2267299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                }
2277299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
2287299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2297299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2307299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onProviderDisabled(String provider) {
2317299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2327299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2337299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onProviderEnabled(String provider) {
2347299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2357299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2367299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void onStatusChanged(String provider, int status, Bundle extras) {
2377299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2387299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2397299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        /*
2407299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn         * The user has moved if the accuracy circles of the two locations
2417299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn         * don't overlap.
2427299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn         */
2437299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        private boolean hasMoved(Location location) {
2447299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (location == null) {
2457299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                return false;
2467299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
2477299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (mLocation == null) {
2487299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                return true;
2497299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
2507299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2517299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            /* if new location is older than the current one, the devices hasn't
2527299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn             * moved.
2537299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn             */
2547299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (location.getTime() < mLocation.getTime()) {
2557299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                return false;
2567299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
2577299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2587299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            /* Get the distance between the two points */
2597299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            float distance = mLocation.distanceTo(location);
2607299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2617299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            /* Get the total accuracy radius for both locations */
2627299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            float totalAccuracy = mLocation.getAccuracy() + location.getAccuracy();
2637299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2647299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            /* If the distance is greater than the combined accuracy of the two
2657299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn             * points then they can't overlap and hence the user has moved.
2667299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn             */
2677299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            return distance >= totalAccuracy;
2687299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
2697299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    };
2707299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2717299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    public UiModeManagerService(Context context) {
2727299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mContext = context;
2737299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2747299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        ServiceManager.addService(Context.UI_MODE_SERVICE, this);
275ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
2767299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mAlarmManager =
2777299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
2787299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mLocationManager =
2797299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
2807299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mContext.registerReceiver(mTwilightUpdateReceiver,
2817299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                new IntentFilter(ACTION_UPDATE_NIGHT_MODE));
2827299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mContext.registerReceiver(mDockModeReceiver,
2837299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                new IntentFilter(Intent.ACTION_DOCK_EVENT));
284e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood        mContext.registerReceiver(mBatteryReceiver,
285e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
286e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood
287e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood        PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
288e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood        mWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
2897299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
2907299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mConfiguration.setToDefaults();
291e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood
292e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood        mCarModeKeepsScreenOn = (context.getResources().getInteger(
293e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
294e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood        mDeskModeKeepsScreenOn = (context.getResources().getInteger(
295e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
2962ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn
2972ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn        mNightMode = Settings.Secure.getInt(mContext.getContentResolver(),
2982ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                Settings.Secure.UI_NIGHT_MODE, UiModeManager.MODE_NIGHT_AUTO);
2997299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
3007299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
301d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn    public void disableCarMode(int flags) {
3027299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        synchronized (mLock) {
3037299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            setCarModeLocked(false);
304924e164a83056600642a3181f19094b3ecb5262dMike Lockwood            if (mSystemReady) {
305d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                updateLocked(flags);
306924e164a83056600642a3181f19094b3ecb5262dMike Lockwood            }
3077299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
3087299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
3097299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
3107299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    public void enableCarMode() {
3117299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        synchronized (mLock) {
3127299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            setCarModeLocked(true);
313924e164a83056600642a3181f19094b3ecb5262dMike Lockwood            if (mSystemReady) {
314d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                updateLocked(0);
315924e164a83056600642a3181f19094b3ecb5262dMike Lockwood            }
3167299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
3177299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
3187299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
3197299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    public int getCurrentModeType() {
3207299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        synchronized (mLock) {
3217299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
3227299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
3237299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
324ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
3257299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    public void setNightMode(int mode) throws RemoteException {
3267299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        synchronized (mLock) {
3277299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            switch (mode) {
3287299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                case UiModeManager.MODE_NIGHT_NO:
3297299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                case UiModeManager.MODE_NIGHT_YES:
3307299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                case UiModeManager.MODE_NIGHT_AUTO:
3317299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    break;
3327299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                default:
3337299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    throw new IllegalArgumentException("Unknown mode: " + mode);
3347299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
3357299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (!isDoingNightMode()) {
3367299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                return;
3377299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
338ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
3397299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (mNightMode != mode) {
3402ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                long ident = Binder.clearCallingIdentity();
3412ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                Settings.Secure.putInt(mContext.getContentResolver(),
3422ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                        Settings.Secure.UI_NIGHT_MODE, mode);
3432ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                Binder.restoreCallingIdentity(ident);
3447299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mNightMode = mode;
345d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                updateLocked(0);
3467299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
3477299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
3487299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
349ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
3507299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    public int getNightMode() throws RemoteException {
3517299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        return mNightMode;
3527299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
353ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
3547299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    void systemReady() {
3557299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        synchronized (mLock) {
3567299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            mSystemReady = true;
3577299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            mCarModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
358d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn            updateLocked(0);
3597299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            mHandler.sendEmptyMessage(MSG_ENABLE_LOCATION_UPDATES);
3607299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
3617299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
3627299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
3637299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    boolean isDoingNightMode() {
3647299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        return mCarModeEnabled || mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
3657299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
366ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
3677299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    void setCarModeLocked(boolean enabled) {
3687299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (mCarModeEnabled != enabled) {
3697299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            mCarModeEnabled = enabled;
3707299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
3717299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
3727299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
3737299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    void updateDockState(int newState) {
3747299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        synchronized (mLock) {
3757299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (newState != mDockState) {
3767299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mDockState = newState;
377924e164a83056600642a3181f19094b3ecb5262dMike Lockwood                setCarModeLocked(mDockState == Intent.EXTRA_DOCK_STATE_CAR);
3787299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                if (mSystemReady) {
379d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                    updateLocked(0);
3807299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                }
3817299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
3827299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
3837299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
384e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood
3852ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn    final void updateConfigurationLocked(boolean sendIt) {
386b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        int uiMode = 0;
387b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        if (mCarModeEnabled) {
388b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn            uiMode = Configuration.UI_MODE_TYPE_CAR;
389b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
390b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn            uiMode = Configuration.UI_MODE_TYPE_DESK;
391b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        }
3929c9c532d3625ba2485eb4ea6924ed0a0163fd958Dianne Hackborn        if (mCarModeEnabled) {
393b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn            if (mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
394b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                updateTwilightLocked();
395b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                uiMode |= mComputedNightMode ? Configuration.UI_MODE_NIGHT_YES
396b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                        : Configuration.UI_MODE_NIGHT_NO;
3977299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            } else {
398b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                uiMode |= mNightMode << 4;
3997299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
400b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        } else {
401b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn            // Disabling the car mode clears the night mode.
402b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn            uiMode = Configuration.UI_MODE_TYPE_NORMAL |
403b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    Configuration.UI_MODE_NIGHT_NO;
404b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        }
405ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
406b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        mCurUiMode = uiMode;
407ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
408b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        if (!mHoldingConfiguration && uiMode != mSetUiMode) {
409b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn            mSetUiMode = uiMode;
4102ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn            mConfiguration.uiMode = uiMode;
411ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
4122ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn            if (sendIt) {
4132ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                try {
4142ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    ActivityManagerNative.getDefault().updateConfiguration(mConfiguration);
4152ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                } catch (RemoteException e) {
4162ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                    Slog.w(TAG, "Failure communicating with activity manager", e);
4172ccda4dc8d800c3592b4bd4d1d70a064d98dd4feDianne Hackborn                }
4187299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
419b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        }
420b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn    }
421ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
422d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn    final void updateLocked(int flags) {
423b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        long ident = Binder.clearCallingIdentity();
424ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
425b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn        try {
4267299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            String action = null;
4277299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            String oldAction = null;
4287299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
429780b2603041a56800ff6e49fb14535c1b1ca8907Tobias Haamel                adjustStatusBarCarModeLocked();
4307299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                oldAction = UiModeManager.ACTION_EXIT_CAR_MODE;
4317299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            } else if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_DESK) {
4327299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
4337299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
434ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
4357299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (mCarModeEnabled) {
4367299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_CAR) {
4377299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    adjustStatusBarCarModeLocked();
438ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
4397299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    if (oldAction != null) {
4407299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mContext.sendBroadcast(new Intent(oldAction));
4417299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
4427299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
4437299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    action = UiModeManager.ACTION_ENTER_CAR_MODE;
4447299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                }
4457299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
4467299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_DESK) {
4477299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    if (oldAction != null) {
4487299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mContext.sendBroadcast(new Intent(oldAction));
4497299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
4507299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    mLastBroadcastState = Intent.EXTRA_DOCK_STATE_DESK;
4517299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    action = UiModeManager.ACTION_ENTER_DESK_MODE;
4527299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                }
4537299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            } else {
4547299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
4557299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                action = oldAction;
4567299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
457ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
4587299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (action != null) {
4597299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                // Send the ordered broadcast; the result receiver will receive after all
4607299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                // broadcasts have been sent. If any broadcast receiver changes the result
4617299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                // code from the initial value of RESULT_OK, then the result receiver will
4627299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                // not launch the corresponding dock application. This gives apps a chance
4637299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                // to override the behavior and stay in their app even when the device is
4647299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                // placed into a dock.
4657299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mContext.sendOrderedBroadcast(new Intent(action), null,
4667299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mResultReceiver, null, Activity.RESULT_OK, null, null);
467b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                // Attempting to make this transition a little more clean, we are going
468b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                // to hold off on doing a configuration change until we have finished
469b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                // the broacast and started the home activity.
470b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                mHoldingConfiguration = true;
4717299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
472ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
473d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn            if (oldAction != null && (flags&UiModeManager.DISABLE_CAR_MODE_GO_HOME) != 0) {
474d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                // We are exiting the special mode, and have been asked to return
475d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                // to the main home screen while doing so.  To keep this clean, we
476d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                // have the activity manager switch the configuration for us at the
477d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                // same time as the switch.
478d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                try {
479d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                    Intent intent = new Intent(Intent.ACTION_MAIN);
480d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                    intent.addCategory(Intent.CATEGORY_HOME);
481d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
482e2522466552f9c6b7fcea866709710f53aa1f2a8Dianne Hackborn                    mHoldingConfiguration = false;
483d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                    updateConfigurationLocked(false);
484d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                    ActivityManagerNative.getDefault().startActivityWithConfig(
485d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                            null, intent, null, null, 0, null, null, 0, false, false,
486d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                            mConfiguration);
487d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                } catch (RemoteException e) {
488d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                    Slog.w(TAG, e.getCause());
489d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                }
490d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn            } else {
491d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                updateConfigurationLocked(true);
492d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn            }
493e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood
494e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood            // keep screen on when charging and in car mode
495e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood            boolean keepScreenOn = mCharging &&
496e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                    ((mCarModeEnabled && mCarModeKeepsScreenOn) ||
497e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                     (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
498e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood            if (keepScreenOn != mWakeLock.isHeld()) {
499e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                if (keepScreenOn) {
500e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                    mWakeLock.acquire();
501e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                } else {
502e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                    mWakeLock.release();
503e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood                }
504e29db6a2d2ba8d9458c88fe6c6dbb2164462773eMike Lockwood            }
5057299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        } finally {
5067299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            Binder.restoreCallingIdentity(ident);
5077299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
5087299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
5097299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5107299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private void adjustStatusBarCarModeLocked() {
5117299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (mStatusBarManager == null) {
5127299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
5137299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
5147299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5157299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        // Fear not: StatusBarService manages a list of requests to disable
5167299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        // features of the status bar; these are ORed together to form the
5177299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        // active disabled list. So if (for example) the device is locked and
5187299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        // the status bar should be totally disabled, the calls below will
5197299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        // have no effect until the device is unlocked.
5207299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (mStatusBarManager != null) {
5217299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            mStatusBarManager.disable(mCarModeEnabled
5227299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                ? StatusBarManager.DISABLE_NOTIFICATION_TICKER
5237299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                : StatusBarManager.DISABLE_NONE);
5247299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
5257299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5267299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (mNotificationManager == null) {
5277299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            mNotificationManager = (NotificationManager)
5287299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    mContext.getSystemService(Context.NOTIFICATION_SERVICE);
5297299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
5307299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5317299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (mNotificationManager != null) {
5327299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (mCarModeEnabled) {
5337299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                Intent carModeOffIntent = new Intent(mContext, DisableCarModeActivity.class);
5347299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5357299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                Notification n = new Notification();
5367299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                n.icon = R.drawable.stat_notify_car_mode;
5377299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                n.defaults = Notification.DEFAULT_LIGHTS;
5387299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                n.flags = Notification.FLAG_ONGOING_EVENT;
5397299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                n.when = 0;
5407299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                n.setLatestEventInfo(
5417299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mContext,
5427299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mContext.getString(R.string.car_mode_disable_notification_title),
5437299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mContext.getString(R.string.car_mode_disable_notification_message),
5447299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        PendingIntent.getActivity(mContext, 0, carModeOffIntent, 0));
5457299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mNotificationManager.notify(0, n);
5467299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            } else {
5477299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mNotificationManager.cancel(0);
5487299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
5497299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
5507299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
5517299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5527299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    private final Handler mHandler = new Handler() {
5537299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5547299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        boolean mPassiveListenerEnabled;
5557299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        boolean mNetworkListenerEnabled;
5567299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5577299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        @Override
5587299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        public void handleMessage(Message msg) {
5597299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            switch (msg.what) {
5607299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                case MSG_UPDATE_TWILIGHT:
5617299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    synchronized (mLock) {
5627299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        if (isDoingNightMode() && mLocation != null
5637299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                                && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
5647299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            updateTwilightLocked();
565d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                            updateLocked(0);
5667299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        }
5677299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
5687299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    break;
5697299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                case MSG_ENABLE_LOCATION_UPDATES:
5707299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    // enable network provider to receive at least location updates for a given
5717299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    // distance.
5727299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    boolean networkLocationEnabled;
5737299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    try {
5747299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        networkLocationEnabled =
5757299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
5767299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    } catch (Exception e) {
5777299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        // we may get IllegalArgumentException if network location provider
5787299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        // does not exist or is not yet installed.
5797299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        networkLocationEnabled = false;
5807299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
5817299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    if (!mNetworkListenerEnabled && networkLocationEnabled) {
5827299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mNetworkListenerEnabled = true;
5837299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
5847299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                                LOCATION_UPDATE_MS, 0, mEmptyLocationListener);
5857299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
5867299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        if (mLocation == null) {
5877299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            retrieveLocation();
5887299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        }
5897299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        synchronized (mLock) {
5907299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            if (isDoingNightMode() && mLocation != null
5917299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                                    && mNightMode == UiModeManager.MODE_NIGHT_AUTO) {
5927299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                                updateTwilightLocked();
593d49258fed489bcd72a2b2a6ce3a3c38d4b2531e6Dianne Hackborn                                updateLocked(0);
5947299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            }
5957299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        }
5967299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
5977299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                   // enable passive provider to receive updates from location fixes (gps
5987299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                   // and network).
5997299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                   boolean passiveLocationEnabled;
6007299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    try {
6017299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        passiveLocationEnabled =
6027299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            mLocationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER);
6037299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    } catch (Exception e) {
6047299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        // we may get IllegalArgumentException if passive location provider
6057299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        // does not exist or is not yet installed.
6067299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        passiveLocationEnabled = false;
6077299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
6087299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    if (!mPassiveListenerEnabled && passiveLocationEnabled) {
6097299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mPassiveListenerEnabled = true;
6107299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mLocationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER,
6117299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                                0, LOCATION_UPDATE_DISTANCE_METER , mLocationListener);
6127299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
6137299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    if (!(mNetworkListenerEnabled && mPassiveListenerEnabled)) {
6147299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        long interval = msg.getData().getLong(KEY_LAST_UPDATE_INTERVAL);
6157299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        interval *= 1.5;
6167299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        if (interval == 0) {
6177299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            interval = LOCATION_UPDATE_ENABLE_INTERVAL_MIN;
6187299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        } else if (interval > LOCATION_UPDATE_ENABLE_INTERVAL_MAX) {
6197299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                            interval = LOCATION_UPDATE_ENABLE_INTERVAL_MAX;
6207299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        }
6217299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        Bundle bundle = new Bundle();
6227299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        bundle.putLong(KEY_LAST_UPDATE_INTERVAL, interval);
6237299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        Message newMsg = mHandler.obtainMessage(MSG_ENABLE_LOCATION_UPDATES);
6247299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        newMsg.setData(bundle);
6257299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mHandler.sendMessageDelayed(newMsg, interval);
6267299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    }
6277299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    break;
6287299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
6297299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
6307299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
6317299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        private void retrieveLocation() {
632ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey            Location location = null;
633ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey            final Iterator<String> providers =
634ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey                    mLocationManager.getProviders(new Criteria(), true).iterator();
635ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey            while (providers.hasNext()) {
636ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey                final Location lastKnownLocation =
637ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey                        mLocationManager.getLastKnownLocation(providers.next());
638ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey                // pick the most recent location
639ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey                if (location == null || (lastKnownLocation != null &&
640ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey                        location.getTime() < lastKnownLocation.getTime())) {
641ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey                    location = lastKnownLocation;
642ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey                }
643ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey            }
6447299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            // In the case there is no location available (e.g. GPS fix or network location
6457299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            // is not available yet), the longitude of the location is estimated using the timezone,
6467299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            // latitude and accuracy are set to get a good average.
6477299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (location == null) {
6487299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                Time currentTime = new Time();
6497299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                currentTime.set(System.currentTimeMillis());
6507299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                double lngOffset = FACTOR_GMT_OFFSET_LONGITUDE *
6517299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        (currentTime.gmtoff - (currentTime.isDst > 0 ? 3600 : 0));
6527299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                location = new Location("fake");
6537299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                location.setLongitude(lngOffset);
6547299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                location.setLatitude(0);
6557299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                location.setAccuracy(417000.0f);
6567299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                location.setTime(System.currentTimeMillis());
6577299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
6587299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            synchronized (mLock) {
6597299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mLocation = location;
6607299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
6617299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
6627299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    };
6637299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
6647299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    void updateTwilightLocked() {
6657299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (mLocation == null) {
6667299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            return;
6677299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
6687299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        final long currentTime = System.currentTimeMillis();
6697299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        boolean nightMode;
6707299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        // calculate current twilight
6717299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        TwilightCalculator tw = new TwilightCalculator();
6727299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        tw.calculateTwilight(currentTime,
6737299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                mLocation.getLatitude(), mLocation.getLongitude());
6747299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (tw.mState == TwilightCalculator.DAY) {
6757299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            nightMode = false;
6767299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        } else {
6777299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            nightMode = true;
6787299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
6797299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
6807299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        // schedule next update
6817299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        long nextUpdate = 0;
6827299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (tw.mSunrise == -1 || tw.mSunset == -1) {
6837299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            // In the case the day or night never ends the update is scheduled 12 hours later.
6847299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            nextUpdate = currentTime + 12 * DateUtils.HOUR_IN_MILLIS;
6857299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        } else {
6867299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            final int mLastTwilightState = tw.mState;
6877299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            // add some extra time to be on the save side.
6887299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            nextUpdate += DateUtils.MINUTE_IN_MILLIS;
6897299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (currentTime > tw.mSunset) {
6907299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                // next update should be on the following day
6917299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                tw.calculateTwilight(currentTime
6927299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        + DateUtils.DAY_IN_MILLIS, mLocation.getLatitude(),
6937299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                        mLocation.getLongitude());
6947299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
6957299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
6967299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (mLastTwilightState == TwilightCalculator.NIGHT) {
6977299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                nextUpdate += tw.mSunrise;
6987299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            } else {
6997299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                nextUpdate += tw.mSunset;
7007299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
7017299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
7027299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
7037299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        Intent updateIntent = new Intent(ACTION_UPDATE_NIGHT_MODE);
7047299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        PendingIntent pendingIntent =
7057299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                PendingIntent.getBroadcast(mContext, 0, updateIntent, 0);
7067299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mAlarmManager.cancel(pendingIntent);
7077299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mAlarmManager.set(AlarmManager.RTC_WAKEUP, nextUpdate, pendingIntent);
7087299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn
7097299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        mComputedNightMode = nightMode;
7107299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
711ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
7127299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    @Override
7137299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
7147299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
7157299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                != PackageManager.PERMISSION_GRANTED) {
716ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
7177299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            pw.println("Permission Denial: can't dump uimode service from from pid="
7187299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    + Binder.getCallingPid()
7197299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    + ", uid=" + Binder.getCallingUid());
7207299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            return;
7217299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
722ba9ab183186cb2ef704759485a8481d5b8c8a650Bernd Holzhey
7237299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        synchronized (mLock) {
7247299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            pw.println("Current UI Mode Service state:");
7257299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            pw.print("  mDockState="); pw.print(mDockState);
7267299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
7277299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            pw.print("  mNightMode="); pw.print(mNightMode);
7287299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
7297299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    pw.print(" mComputedNightMode="); pw.println(mComputedNightMode);
7307299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            pw.print("  mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
731b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn                    pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
732b8b11a0b1d82e24f7a79f2e1672e7f5cf1611a55Dianne Hackborn            pw.print("  mHoldingConfiguration="); pw.print(mHoldingConfiguration);
7337299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                    pw.print(" mSystemReady="); pw.println(mSystemReady);
7347299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            if (mLocation != null) {
7357299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn                pw.print("  mLocation="); pw.println(mLocation);
7367299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn            }
7377299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn        }
7387299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn    }
7397299c41630935a2b106e73e5603579a7747f7535Dianne Hackborn}
740