Add a class to compute the sunrise/sunset based on timezone/location.
Change-Id: I9c01ca2e51093488153e53f7b27d1c9ea1a9e193
diff --git a/src/com/android/wallpaper/RenderScriptWallpaper.java b/src/com/android/wallpaper/RenderScriptWallpaper.java
index 3a4fc6b..afc6e0c 100644
--- a/src/com/android/wallpaper/RenderScriptWallpaper.java
+++ b/src/com/android/wallpaper/RenderScriptWallpaper.java
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
package com.android.wallpaper;
import android.service.wallpaper.WallpaperService;
diff --git a/src/com/android/wallpaper/grass/SunCalculator.java b/src/com/android/wallpaper/grass/SunCalculator.java
new file mode 100644
index 0000000..7bf730c
--- /dev/null
+++ b/src/com/android/wallpaper/grass/SunCalculator.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Based on sunrisesunsetlib-java:
+ * Copyright 2008-2009 Mike Reedell / LuckyCatLabs.
+ *
+ * Original project and source can be found at:
+ * http://mikereedell.github.com/sunrisesunsetlib-java/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wallpaper.grass;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import android.location.Location;
+
+class SunCalculator {
+ /** Astronomical sunrise/set is when the sun is 18 degrees below the horizon. */
+ static final double ZENITH_ASTRONOMICAL = 108;
+
+ /** Nautical sunrise/set is when the sun is 12 degrees below the horizon. */
+ static final double ZENITH_NAUTICAL = 102;
+
+ /** Civil sunrise/set (dawn/dusk) is when the sun is 6 degrees below the horizon. */
+ static final double ZENITH_CIVIL = 96;
+
+ /** Official sunrise/set is when the sun is 50' below the horizon. */
+ static final double ZENITH_OFFICIAL = 90.8333;
+
+ private Location mLocation;
+ private TimeZone mTimeZone;
+
+ SunCalculator(Location location, String timeZoneIdentifier) {
+ mLocation = location;
+ mTimeZone = TimeZone.getTimeZone(timeZoneIdentifier);
+ }
+
+ public void setLocation(Location location) {
+ mLocation = location;
+ }
+
+ /**
+ * Computes the sunrise time for the given zenith at the given date.
+ *
+ * @param solarZenith <code>Zenith</code> enum corresponding to the type
+ * of sunrise to compute.
+ * @param date <code>Calendar</code> object representing the date to
+ * compute the sunrise for.
+ * @return the sunrise time
+ */
+ public double computeSunriseTime(double solarZenith, Calendar date) {
+ return computeSolarEventTime(solarZenith, date, true);
+ }
+
+ /**
+ * Computes the sunset time for the given zenith at the given date.
+ *
+ * @param solarZenith <code>Zenith</code> enum corresponding to the type of
+ * sunset to compute.
+ * @param date <code>Calendar</code> object representing the date to compute
+ * the sunset for.
+ * @return the sunset time
+ */
+ public double computeSunsetTime(double solarZenith, Calendar date) {
+ return computeSolarEventTime(solarZenith, date, false);
+ }
+
+ public static int timeToHours(double time) {
+ int hour = (int) Math.floor(time);
+ int minute = (int) Math.round((time - hour) * 60);
+ if (minute == 60) {
+ hour++;
+ }
+ return hour;
+ }
+
+ public static int timeToMinutes(double time) {
+ int hour = (int) Math.floor(time);
+ int minute = (int) Math.round((time - hour) * 60);
+ if (minute == 60) {
+ minute = 0;
+ }
+ return minute;
+ }
+
+ public static float timeToDayFraction(double time) {
+ int hour = (int) Math.floor(time);
+ int minute = (int) Math.round((time - hour) * 60);
+ if (minute == 60) {
+ minute = 0;
+ hour++;
+ }
+ return (hour * 60 + minute) / 1440.0f;
+ }
+
+ public static String timeToString(double time) {
+ StringBuffer buffer = new StringBuffer();
+ int hour = (int) Math.floor(time);
+ int minute = (int) Math.round((time - hour) * 60);
+ if (minute == 60) {
+ minute = 0;
+ hour++;
+ }
+ buffer.append(hour).append(':').append(minute < 10 ? "0" + minute : minute);
+ return buffer.toString();
+ }
+
+ private double computeSolarEventTime(double solarZenith, Calendar date, boolean isSunrise) {
+ date.setTimeZone(mTimeZone);
+ double longitudeHour = getLongitudeHour(date, isSunrise);
+ double meanAnomaly = getMeanAnomaly(longitudeHour);
+ double sunTrueLong = getSunTrueLongitude(meanAnomaly);
+ double cosineSunLocalHour = getCosineSunLocalHour(sunTrueLong, solarZenith);
+ if ((cosineSunLocalHour < -1.0) || (cosineSunLocalHour > 1.0)) {
+ return 0;
+ }
+
+ double sunLocalHour = getSunLocalHour(cosineSunLocalHour, isSunrise);
+ double localMeanTime = getLocalMeanTime(sunTrueLong, longitudeHour, sunLocalHour);
+ return getLocalTime(localMeanTime, date);
+ }
+
+ /**
+ * Computes the base longitude hour, lngHour in the algorithm.
+ *
+ * @return the longitude of the location of the solar event divided by 15 (deg/hour), in
+ * <code>double</code> form.
+ */
+ private double getBaseLongitudeHour() {
+ return mLocation.getLongitude() / 15.0;
+ }
+
+ /**
+ * Computes the longitude time, t in the algorithm.
+ *
+ * @return longitudinal time in <code>double</code> form.
+ */
+ private double getLongitudeHour(Calendar date, Boolean isSunrise) {
+ int offset = 18;
+ if (isSunrise) {
+ offset = 6;
+ }
+ double dividend = offset - getBaseLongitudeHour();
+ double addend = dividend / 24.0;
+ return getDayOfYear(date) + addend;
+ }
+
+ /**
+ * Computes the mean anomaly of the Sun, M in the algorithm.
+ *
+ * @return the suns mean anomaly, M, in <code>double</code> form.
+ */
+ private static double getMeanAnomaly(double longitudeHour) {
+ return 0.9856 * longitudeHour - 3.289;
+ }
+
+ /**
+ * Computes the true longitude of the sun, L in the algorithm, at the given
+ * location, adjusted to fit in the range [0-360].
+ *
+ * @param meanAnomaly the suns mean anomaly.
+ * @return the suns true longitude, in <code>double</code> form.
+ */
+ private static double getSunTrueLongitude(double meanAnomaly) {
+ final double meanRadians = Math.toRadians(meanAnomaly);
+ double sinMeanAnomaly = Math.sin(meanRadians);
+ double sinDoubleMeanAnomaly = Math.sin((meanRadians * 2.0));
+
+ double firstPart = meanAnomaly + sinMeanAnomaly * 1.916;
+ double secondPart = sinDoubleMeanAnomaly * 0.020 + 282.634;
+ double trueLongitude = firstPart + secondPart;
+
+ if (trueLongitude > 360) {
+ trueLongitude = trueLongitude - 360.0;
+ }
+ return trueLongitude;
+ }
+
+ /**
+ * Computes the suns right ascension, RA in the algorithm, adjusting for
+ * the quadrant of L and turning it into degree-hours. Will be in the
+ * range [0,360].
+ *
+ * @param sunTrueLong Suns true longitude, in <code>double</code>
+ * @return suns right ascension in degree-hours, in <code>double</code> form.
+ */
+ private static double getRightAscension(double sunTrueLong) {
+ double tanL = Math.tan(Math.toRadians(sunTrueLong));
+
+ double innerParens = Math.toDegrees(tanL) * 0.91764;
+ double rightAscension = Math.atan(Math.toRadians(innerParens));
+ rightAscension = Math.toDegrees(rightAscension);
+
+ if (rightAscension < 0.0) {
+ rightAscension = rightAscension + 360.0;
+ } else if (rightAscension > 360.0) {
+ rightAscension = rightAscension - 360.0;
+ }
+
+ double ninety = 90.0;
+ double longitudeQuadrant = (int) (sunTrueLong / ninety);
+ longitudeQuadrant = longitudeQuadrant * ninety;
+
+ double rightAscensionQuadrant = (int) (rightAscension / ninety);
+ rightAscensionQuadrant = rightAscensionQuadrant * ninety;
+
+ double augend = longitudeQuadrant - rightAscensionQuadrant;
+ return (rightAscension + augend) / 15.0;
+ }
+
+ private double getCosineSunLocalHour(double sunTrueLong, double zenith) {
+ double sinSunDeclination = getSinOfSunDeclination(sunTrueLong);
+ double cosineSunDeclination = getCosineOfSunDeclination(sinSunDeclination);
+
+ final double zenithInRads = Math.toRadians(zenith);
+ final double latitude = Math.toRadians(mLocation.getLatitude());
+
+ double cosineZenith = Math.cos(zenithInRads);
+ double sinLatitude = Math.sin(latitude);
+ double cosLatitude = Math.cos(latitude);
+
+ double sinDeclinationTimesSinLat = sinSunDeclination * sinLatitude;
+ double dividend = cosineZenith - sinDeclinationTimesSinLat;
+ double divisor = cosineSunDeclination * cosLatitude;
+
+ return dividend / divisor;
+ }
+
+ private static double getSinOfSunDeclination(double sunTrueLong) {
+ double sinTrueLongitude = Math.sin(Math.toRadians(sunTrueLong));
+ return sinTrueLongitude * 0.39782;
+ }
+
+ private static double getCosineOfSunDeclination(double sinSunDeclination) {
+ double arcSinOfSinDeclination = Math.asin(sinSunDeclination);
+ return Math.cos(arcSinOfSinDeclination);
+ }
+
+ private static double getSunLocalHour(double cosineSunLocalHour, Boolean isSunrise) {
+ double arcCosineOfCosineHourAngle = Math.acos(cosineSunLocalHour);
+ double localHour = Math.toDegrees(arcCosineOfCosineHourAngle);
+ if (isSunrise) {
+ localHour = 360.0 - localHour;
+ }
+ return localHour / 15.0;
+ }
+
+ private static double getLocalMeanTime(double sunTrueLong, double longitudeHour,
+ double sunLocalHour) {
+
+ double rightAscension = getRightAscension(sunTrueLong);
+ double innerParens = longitudeHour * 0.06571;
+ double localMeanTime = sunLocalHour + rightAscension - innerParens;
+ localMeanTime = localMeanTime - 6.622;
+
+ if (localMeanTime < 0.0) {
+ localMeanTime = localMeanTime + 24.0;
+ } else if (localMeanTime > 24.0) {
+ localMeanTime = localMeanTime - 24.0;
+ }
+ return localMeanTime;
+ }
+
+ private double getLocalTime(double localMeanTime, Calendar date) {
+ double utcTime = localMeanTime - getBaseLongitudeHour();
+ double utcOffSet = getUTCOffSet(date);
+ double utcOffSetTime = utcTime + utcOffSet;
+ return adjustForDST(utcOffSetTime, date);
+ }
+
+ private double adjustForDST(double localMeanTime, Calendar date) {
+ double localTime = localMeanTime;
+ if (mTimeZone.inDaylightTime(date.getTime())) {
+ localTime++;
+ }
+ if (localTime > 24.0) {
+ localTime = localTime - 24.0;
+ }
+ return localTime;
+ }
+
+ /**
+ * ****** UTILITY METHODS (Should probably go somewhere else. *****************
+ */
+
+ private static double getDayOfYear(Calendar date) {
+ return date.get(Calendar.DAY_OF_YEAR);
+ }
+
+ private static double getUTCOffSet(Calendar date) {
+ int offSetInMillis = date.get(Calendar.ZONE_OFFSET);
+ return offSetInMillis / 3600000;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/wallpaper/polarclock/PolarClockWallpaper.java b/src/com/android/wallpaper/polarclock/PolarClockWallpaper.java
index 5b4a060..ab0452a 100644
--- a/src/com/android/wallpaper/polarclock/PolarClockWallpaper.java
+++ b/src/com/android/wallpaper/polarclock/PolarClockWallpaper.java
@@ -29,7 +29,6 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.XmlResourceParser;
-import android.preference.ListPreference;
import android.os.Handler;
import android.os.SystemClock;
@@ -108,7 +107,6 @@
private FixedClockPalette() { }
- @Override
public static ClockPalette parseXmlPaletteTag(XmlResourceParser xrp) {
final FixedClockPalette pal = new FixedClockPalette();
pal.mId = xrp.getAttributeValue(null, "id");
@@ -199,7 +197,6 @@
}
}
- @Override
public static ClockPalette parseXmlPaletteTag(XmlResourceParser xrp) {
final CyclingClockPalette pal = new CyclingClockPalette();
pal.mId = xrp.getAttributeValue(null, "id");