Fix calculation of the next twilight update for locations where the day or night never ends.
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 606b589..027f35c 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -416,7 +416,7 @@
                         mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                                 LOCATION_UPDATE_MS, LOCATION_UPDATE_DISTANCE_METER, mLocationListener);
                         retrieveLocation();
-                        if (mLocation != null) {
+                        if (mCarModeEnabled && mLocation != null && mNightMode == MODE_NIGHT_AUTO) {
                             try {
                                 DockObserver.this.updateTwilight();
                             } catch (RemoteException e) {
@@ -462,8 +462,8 @@
             if (location == null) {
                 Time currentTime = new Time();
                 currentTime.set(System.currentTimeMillis());
-                double lngOffset = FACTOR_GMT_OFFSET_LONGITUDE * currentTime.gmtoff
-                        - (currentTime.isDst > 0 ? 3600 : 0);
+                double lngOffset = FACTOR_GMT_OFFSET_LONGITUDE *
+                        (currentTime.gmtoff - (currentTime.isDst > 0 ? 3600 : 0));
                 location = new Location("fake");
                 location.setLongitude(lngOffset);
                 location.setLatitude(59.95);
@@ -587,20 +587,26 @@
             }
 
             // schedule next update
-            final int mLastTwilightState = tw.mState;
-            // add some extra time to be on the save side.
-            long nextUpdate = DateUtils.MINUTE_IN_MILLIS;
-            if (currentTime > tw.mSunset) {
-                // next update should be on the following day
-                tw.calculateTwilight(currentTime
-                        + DateUtils.DAY_IN_MILLIS, mLocation.getLatitude(),
-                        mLocation.getLongitude());
-            }
-
-            if (mLastTwilightState == TwilightCalculator.NIGHT) {
-                nextUpdate += tw.mSunrise;
+            long nextUpdate = 0;
+            if (tw.mSunrise == -1 || tw.mSunset == -1) {
+                // In the case the day or night never ends the update is scheduled 12 hours later.
+                nextUpdate = currentTime + 12 * DateUtils.HOUR_IN_MILLIS;
             } else {
-                nextUpdate += tw.mSunset;
+                final int mLastTwilightState = tw.mState;
+                // add some extra time to be on the save side.
+                nextUpdate += DateUtils.MINUTE_IN_MILLIS;
+                if (currentTime > tw.mSunset) {
+                    // next update should be on the following day
+                    tw.calculateTwilight(currentTime
+                            + DateUtils.DAY_IN_MILLIS, mLocation.getLatitude(),
+                            mLocation.getLongitude());
+                }
+
+                if (mLastTwilightState == TwilightCalculator.NIGHT) {
+                    nextUpdate += tw.mSunrise;
+                } else {
+                    nextUpdate += tw.mSunset;
+                }
             }
 
             Intent updateIntent = new Intent(ACTION_UPDATE_NIGHT_MODE);
@@ -609,8 +615,11 @@
             mAlarmManager.cancel(pendingIntent);
             mAlarmManager.set(AlarmManager.RTC_WAKEUP, nextUpdate, pendingIntent);
 
-            // set current mode
-            setMode(Configuration.UI_MODE_TYPE_CAR, nightMode << 4);
+            // Make sure that we really set the new mode only if we're in car mode and
+            // automatic switching is enables.
+            if (mCarModeEnabled && mNightMode == MODE_NIGHT_AUTO) {
+                setMode(Configuration.UI_MODE_TYPE_CAR, nightMode << 4);
+            }
         }
     }
 
diff --git a/services/java/com/android/server/TwilightCalculator.java b/services/java/com/android/server/TwilightCalculator.java
index a8f67d8..a5c93b5 100644
--- a/services/java/com/android/server/TwilightCalculator.java
+++ b/services/java/com/android/server/TwilightCalculator.java
@@ -46,10 +46,16 @@
     // Java time on Jan 1, 2000 12:00 UTC.
     private static final long UTC_2000 = 946728000000L;
 
-    /** Time of sunset (civil twilight) in milliseconds. */
+    /**
+     * Time of sunset (civil twilight) in milliseconds or -1 in the case the day
+     * or night never ends.
+     */
     public long mSunset;
 
-    /** Time of sunrise (civil twilight) in milliseconds. */
+    /**
+     * Time of sunrise (civil twilight) in milliseconds or -1 in the case the
+     * day or night never ends.
+     */
     public long mSunrise;
 
     /** Current state */
@@ -85,10 +91,24 @@
         double solarDec = Math.asin(FloatMath.sin(solarLng) * FloatMath.sin(OBLIQUITY));
 
         final double latRad = latiude * DEGREES_TO_RADIANS;
-        float hourAngle = (float) (Math
-                .acos((FloatMath.sin(ALTIDUTE_CORRECTION_CIVIL_TWILIGHT) - Math.sin(latRad)
-                        * Math.sin(solarDec))
-                        / (Math.cos(latRad) * Math.cos(solarDec))) / (2 * Math.PI));
+
+        double cosHourAngle = (FloatMath.sin(ALTIDUTE_CORRECTION_CIVIL_TWILIGHT) - Math.sin(latRad)
+                * Math.sin(solarDec)) / (Math.cos(latRad) * Math.cos(solarDec));
+        // The day or night never ends for the given date and location, if this value is out of
+        // range.
+        if (cosHourAngle >= 1) {
+            mState = NIGHT;
+            mSunset = -1;
+            mSunrise = -1;
+            return;
+        } else if (cosHourAngle <= -1) {
+            mState = DAY;
+            mSunset = -1;
+            mSunrise = -1;
+            return;
+        }
+
+        float hourAngle = (float) (Math.acos(cosHourAngle) / (2 * Math.PI));
 
         mSunset = Math.round((solarTransitJ2000 + hourAngle) * DateUtils.DAY_IN_MILLIS) + UTC_2000;
         mSunrise = Math.round((solarTransitJ2000 - hourAngle) * DateUtils.DAY_IN_MILLIS) + UTC_2000;