Utils.java revision 0b7c93a6b691b25ccbcd8d683774d3d0d351a8e9
1d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson/*
2d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Copyright (C) 2012 The Android Open Source Project
3d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson *
4d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Licensed under the Apache License, Version 2.0 (the "License");
5d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * you may not use this file except in compliance with the License.
6d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * You may obtain a copy of the License at
7d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson *
8d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson *      http://www.apache.org/licenses/LICENSE-2.0
9d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson *
10d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * Unless required by applicable law or agreed to in writing, software
11d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * distributed under the License is distributed on an "AS IS" BASIS,
12d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * See the License for the specific language governing permissions and
14d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson * limitations under the License.
15d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson */
16d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
17d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonpackage com.android.deskclock;
18d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
1978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.animation.Animator;
2078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.animation.AnimatorSet;
2178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.animation.ObjectAnimator;
2278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.animation.TimeInterpolator;
230b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultasimport android.app.AlarmManager;
240b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultasimport android.app.PendingIntent;
25d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.content.Context;
26d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.content.Intent;
27de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelsonimport android.content.SharedPreferences;
28d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.content.pm.PackageInfo;
29d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.content.pm.PackageManager.NameNotFoundException;
30d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelsonimport android.content.res.Resources;
3178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.graphics.Color;
3278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.graphics.Paint;
3378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.graphics.PorterDuff;
3478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.graphics.PorterDuffColorFilter;
35d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.net.Uri;
3678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.os.Handler;
37287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzsteinimport android.os.SystemClock;
3878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.preference.PreferenceManager;
3978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.provider.Settings;
40d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.text.TextUtils;
4178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.text.format.DateFormat;
42d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport android.view.MenuItem;
4378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.view.View;
4478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.view.animation.AccelerateInterpolator;
4578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.view.animation.DecelerateInterpolator;
4678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport android.widget.TextView;
47d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
48de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelsonimport com.android.deskclock.stopwatch.Stopwatches;
4998b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultasimport com.android.deskclock.timer.Timers;
50d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelsonimport com.android.deskclock.worldclock.CityObj;
51de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson
52d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelsonimport java.text.Collator;
53d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelsonimport java.util.Arrays;
5478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzsteinimport java.util.Calendar;
55d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelsonimport java.util.Comparator;
56d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonimport java.util.Locale;
57d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
58d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
59d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelsonpublic class Utils {
60d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    private final static String TAG = Utils.class.getName();
61d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
62d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    private final static String PARAM_LANGUAGE_CODE = "hl";
63d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
64d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    /**
65d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson     * Help URL query parameter key for the app version.
66d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson     */
67d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    private final static String PARAM_VERSION = "version";
68d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
69d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    /**
70d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson     * Cached version code to prevent repeated calls to the package manager.
71d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson     */
72d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    private static String sCachedVersionCode = null;
73d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
7478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    /**
7578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     * Intent to be used for checking if a clock's date has changed. Must be every fifteen
7678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     * minutes because not all time zones are hour-locked.
7778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     **/
7878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    public static final String ACTION_ON_QUARTER_HOUR = "com.android.deskclock.ON_QUARTER_HOUR";
79d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
8078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    /** Types that may be used for clock displays. **/
8178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    public static final String CLOCK_TYPE_DIGITAL = "digital";
8278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    public static final String CLOCK_TYPE_ANALOG = "analog";
83d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
847048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson    /**
857048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson     * time format constants
867048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson     */
877048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson    public final static String HOURS_24 = "kk";
887048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson    public final static String HOURS = "h";
897048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson    public final static String MINUTES = ":mm";
907048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson
917048625adb7c349deab4c00b2d85bcf65c164ae5Isaac Katzenelson
92d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    public static void prepareHelpMenuItem(Context context, MenuItem helpMenuItem) {
93d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        String helpUrlString = context.getResources().getString(R.string.desk_clock_help_url);
94d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        if (TextUtils.isEmpty(helpUrlString)) {
95d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson            // The help url string is empty or null, so set the help menu item to be invisible.
96d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson            helpMenuItem.setVisible(false);
97d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson            return;
98d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        }
99d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        // The help url string exists, so first add in some extra query parameters.  87
100d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        final Uri fullUri = uriWithAddedParameters(context, Uri.parse(helpUrlString));
101d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
102d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        // Then, create an intent that will be fired when the user
103d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        // selects this help menu item.
104d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        Intent intent = new Intent(Intent.ACTION_VIEW, fullUri);
105d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
106d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
107d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
108d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        // Set the intent to the help menu item, show the help menu item in the overflow
109d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        // menu, and make it visible.
110d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        helpMenuItem.setIntent(intent);
111d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        helpMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
112d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        helpMenuItem.setVisible(true);
113d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    }
114d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
115d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    /**
116d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson     * Adds two query parameters into the Uri, namely the language code and the version code
117d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson     * of the app's package as gotten via the context.
118d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson     * @return the uri with added query parameters
119d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson     */
120d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    private static Uri uriWithAddedParameters(Context context, Uri baseUri) {
121d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        Uri.Builder builder = baseUri.buildUpon();
122d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
123d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        // Add in the preferred language
124d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        builder.appendQueryParameter(PARAM_LANGUAGE_CODE, Locale.getDefault().toString());
125d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
126d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        // Add in the package version code
127d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        if (sCachedVersionCode == null) {
128d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson            // There is no cached version code, so try to get it from the package manager.
129d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson            try {
130d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                // cache the version code
131d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                PackageInfo info = context.getPackageManager().getPackageInfo(
132d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                        context.getPackageName(), 0);
133d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                sCachedVersionCode = Integer.toString(info.versionCode);
134d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
135d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                // append the version code to the uri
136d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode);
137d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson            } catch (NameNotFoundException e) {
138d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                // Cannot find the package name, so don't add in the version parameter
139d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                // This shouldn't happen.
140d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson                Log.wtf("Invalid package name for context " + e);
141d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson            }
142d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        } else {
143d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson            builder.appendQueryParameter(PARAM_VERSION, sCachedVersionCode);
144d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        }
145d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
146d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        // Build the full uri and return it
147d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson        return builder.build();
148d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson    }
149d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson
150287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    public static long getTimeNow() {
151287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        return SystemClock.elapsedRealtime();
152287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    }
153287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
15400cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein    /**
15500cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein     * Calculate the amount by which the radius of a CircleTimerView should be offset by the any
15600cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein     * of the extra painted objects.
15700cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein     */
15800cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein    public static float calculateRadiusOffset(
15900cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein            float strokeSize, float diamondStrokeSize, float markerStrokeSize) {
16000cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein        return Math.max(strokeSize, Math.max(diamondStrokeSize, markerStrokeSize));
16100cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein    }
16200cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein
16372332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein    /**  The pressed color used throughout the app. If this method is changed, it will not have
16472332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein     *   any effect on the button press states, and those must be changed separately.
16572332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein    **/
16672332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein    public static int getPressedColorId() {
16772332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein        return R.color.clock_red;
16872332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein    }
16972332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein
17072332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein    /**  The un-pressed color used throughout the app. If this method is changed, it will not have
17172332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein     *   any effect on the button press states, and those must be changed separately.
17272332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein    **/
17372332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein    public static int getGrayColorId() {
17472332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein        return R.color.clock_gray;
17572332c2290d17c344ece074726f72b35ea469f31Sam Blitzstein    }
176de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson
177de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson    /**
178de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson     * Clears the persistent data of stopwatch (start time, state, laps, etc...).
179de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson     */
180de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson    public static void clearSwSharedPref(SharedPreferences prefs) {
181de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        SharedPreferences.Editor editor = prefs.edit();
182de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        editor.remove (Stopwatches.PREF_START_TIME);
183de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        editor.remove (Stopwatches.PREF_ACCUM_TIME);
184de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        editor.remove (Stopwatches.PREF_STATE);
185de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        int lapNum = prefs.getInt(Stopwatches.PREF_LAP_NUM, Stopwatches.STOPWATCH_RESET);
186de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        for (int i = 0; i < lapNum; i++) {
187de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson            String key = Stopwatches.PREF_LAP_TIME + Integer.toString(i);
188de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson            editor.remove(key);
189de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        }
190de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        editor.remove(Stopwatches.PREF_LAP_NUM);
191de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        editor.apply();
192de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson    }
19398b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas
19498b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas    /**
19598b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas     * Broadcast a message to show the in-use timers in the notifications
19698b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas     */
19798b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas    public static void showInUseNotifications(Context context) {
19898b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas        Intent timerIntent = new Intent();
19998b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas        timerIntent.setAction(Timers.NOTIF_IN_USE_SHOW);
20098b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas        context.sendBroadcast(timerIntent);
20198b2b05e7a0cebcd6e065bdd0b25cb6eb86b497cRobyn Coultas    }
20278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
20378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    /** Runnable for use with screensaver and dream, to move the clock every minute.
20478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     *  registerViews() must be called prior to posting.
20578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     */
20678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    public static class ScreensaverMoveSaverRunnable implements Runnable {
20778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        static final long MOVE_DELAY = 60000; // DeskClock.SCREEN_SAVER_MOVE_DELAY;
20878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        static final long SLIDE_TIME = 10000;
20978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        static final long FADE_TIME = 3000;
21078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
21178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        static final boolean SLIDE = false;
21278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
21378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        private View mContentView, mSaverView;
21478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        private final Handler mHandler;
21578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
21678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        private static TimeInterpolator mSlowStartWithBrakes;
21778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
21878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
21978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        public ScreensaverMoveSaverRunnable(Handler handler) {
22078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            mHandler = handler;
22178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            mSlowStartWithBrakes = new TimeInterpolator() {
22278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                @Override
22378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                public float getInterpolation(float x) {
22478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    return (float)(Math.cos((Math.pow(x,3) + 1) * Math.PI) / 2.0f) + 0.5f;
22578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                }
22678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            };
22778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        }
22878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
22978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        public void registerViews(View contentView, View saverView) {
23078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            mContentView = contentView;
23178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            mSaverView = saverView;
23278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        }
23378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
23478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        @Override
23578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        public void run() {
23678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            long delay = MOVE_DELAY;
23778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            if (mContentView == null || mSaverView == null) {
23878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                mHandler.removeCallbacks(this);
23978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                mHandler.postDelayed(this, delay);
24078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                return;
24178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            }
24278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
24378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            final float xrange = mContentView.getWidth() - mSaverView.getWidth();
24478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            final float yrange = mContentView.getHeight() - mSaverView.getHeight();
24578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            Log.v("xrange: "+xrange+" yrange: "+yrange);
24678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
24778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            if (xrange == 0 && yrange == 0) {
24878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                delay = 500; // back in a split second
24978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            } else {
25078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                final int nextx = (int) (Math.random() * xrange);
25178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                final int nexty = (int) (Math.random() * yrange);
25278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
25378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                if (mSaverView.getAlpha() == 0f) {
25478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    // jump right there
25578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    mSaverView.setX(nextx);
25678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    mSaverView.setY(nexty);
25778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    ObjectAnimator.ofFloat(mSaverView, "alpha", 0f, 1f)
25878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        .setDuration(FADE_TIME)
25978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        .start();
26078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                } else {
26178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    AnimatorSet s = new AnimatorSet();
26278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    Animator xMove   = ObjectAnimator.ofFloat(mSaverView,
26378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                                         "x", mSaverView.getX(), nextx);
26478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    Animator yMove   = ObjectAnimator.ofFloat(mSaverView,
26578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                                         "y", mSaverView.getY(), nexty);
26678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
26778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    Animator xShrink = ObjectAnimator.ofFloat(mSaverView, "scaleX", 1f, 0.85f);
26878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    Animator xGrow   = ObjectAnimator.ofFloat(mSaverView, "scaleX", 0.85f, 1f);
26978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
27078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    Animator yShrink = ObjectAnimator.ofFloat(mSaverView, "scaleY", 1f, 0.85f);
27178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    Animator yGrow   = ObjectAnimator.ofFloat(mSaverView, "scaleY", 0.85f, 1f);
27278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    AnimatorSet shrink = new AnimatorSet(); shrink.play(xShrink).with(yShrink);
27378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    AnimatorSet grow = new AnimatorSet(); grow.play(xGrow).with(yGrow);
27478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
27578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    Animator fadeout = ObjectAnimator.ofFloat(mSaverView, "alpha", 1f, 0f);
27678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    Animator fadein = ObjectAnimator.ofFloat(mSaverView, "alpha", 0f, 1f);
27778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
27878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
27978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    if (SLIDE) {
28078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(xMove).with(yMove);
28178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.setDuration(SLIDE_TIME);
28278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
28378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(shrink.setDuration(SLIDE_TIME/2));
28478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(grow.setDuration(SLIDE_TIME/2)).after(shrink);
28578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.setInterpolator(mSlowStartWithBrakes);
28678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    } else {
28778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        AccelerateInterpolator accel = new AccelerateInterpolator();
28878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        DecelerateInterpolator decel = new DecelerateInterpolator();
28978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
29078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        shrink.setDuration(FADE_TIME).setInterpolator(accel);
29178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        fadeout.setDuration(FADE_TIME).setInterpolator(accel);
29278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        grow.setDuration(FADE_TIME).setInterpolator(decel);
29378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        fadein.setDuration(FADE_TIME).setInterpolator(decel);
29478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(shrink);
29578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(fadeout);
29678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(xMove.setDuration(0)).after(FADE_TIME);
29778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(yMove.setDuration(0)).after(FADE_TIME);
29878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(fadein).after(FADE_TIME);
29978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        s.play(grow).after(FADE_TIME);
30078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    }
30178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    s.start();
30278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                }
30378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
30478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                long now = System.currentTimeMillis();
30578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                long adjust = (now % 60000);
30678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                delay = delay
30778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        + (MOVE_DELAY - adjust) // minute aligned
30878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        - (SLIDE ? 0 : FADE_TIME) // start moving before the fade
30978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        ;
31078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            }
31178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
31278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            mHandler.removeCallbacks(this);
31378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            mHandler.postDelayed(this, delay);
31478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        }
31578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    }
31678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
31778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    /** Setup to find out when the quarter-hour changes (e.g. Kathmandu is GMT+5:45) **/
3180b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas    private static long getAlarmOnQuarterHour() {
31978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        Calendar nextQuarter = Calendar.getInstance();
32078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        //  Set 1 second to ensure quarter-hour threshold passed.
32178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        nextQuarter.set(Calendar.SECOND, 1);
32278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        int minute = nextQuarter.get(Calendar.MINUTE);
32378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        nextQuarter.add(Calendar.MINUTE, 15 - (minute % 15));
32478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        long alarmOnQuarterHour = nextQuarter.getTimeInMillis();
32578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        if (0 >= (alarmOnQuarterHour - System.currentTimeMillis())
32678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                || (alarmOnQuarterHour - System.currentTimeMillis()) > 901000) {
32778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            Log.wtf("quarterly alarm calculation error");
32878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        }
32978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        return alarmOnQuarterHour;
33078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    }
33178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
3320b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas    /** Setup alarm refresh when the quarter-hour changes **/
3330b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas    public static PendingIntent startAlarmOnQuarterHour(Context context) {
3340b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas        if (context != null) {
3350b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas            PendingIntent quarterlyIntent = PendingIntent.getBroadcast(
3360b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas                    context, 0, new Intent(Utils.ACTION_ON_QUARTER_HOUR), 0);
3370b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas            ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setRepeating(
3380b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas                    AlarmManager.RTC, getAlarmOnQuarterHour(),
3390b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas                    AlarmManager.INTERVAL_FIFTEEN_MINUTES, quarterlyIntent);
3400b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas            return quarterlyIntent;
3410b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas        } else {
3420b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas            return null;
3430b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas        }
3440b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas    }
3450b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas
3460b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas    public static void cancelAlarmOnQuarterHour(Context context, PendingIntent quarterlyIntent) {
3470b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas        if (quarterlyIntent != null && context != null) {
3480b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas            ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).cancel(
3490b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas                    quarterlyIntent);
3500b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas        }
3510b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas    }
3520b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas
3530b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas    public static PendingIntent refreshAlarmOnQuarterHour(
3540b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas            Context context, PendingIntent quarterlyIntent) {
3550b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas        cancelAlarmOnQuarterHour(context, quarterlyIntent);
3560b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas        return startAlarmOnQuarterHour(context);
3570b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas    }
3580b7c93a6b691b25ccbcd8d683774d3d0d351a8e9Robyn Coultas
35978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    /**
36078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     * For screensavers to set whether the digital or analog clock should be displayed.
36178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     * Returns the view to be displayed.
36278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     */
36378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    public static View setClockStyle(Context context, View digitalClock, View analogClock,
36478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            String clockStyleKey) {
36578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
36678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        String defaultClockStyle = context.getResources().getString(R.string.default_clock_style);
36778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        String style = sharedPref.getString(clockStyleKey, defaultClockStyle);
36878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        View returnView;
36978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        if (style.equals(CLOCK_TYPE_ANALOG)) {
37078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            digitalClock.setVisibility(View.GONE);
37178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            analogClock.setVisibility(View.VISIBLE);
37278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            returnView = analogClock;
37378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        } else {
37478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            digitalClock.setVisibility(View.VISIBLE);
37578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            analogClock.setVisibility(View.GONE);
37678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            returnView = digitalClock;
37778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        }
37878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
37978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        return returnView;
38078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    }
38178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
38278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    /**
38378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     * For screensavers to dim the lights if necessary.
38478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein     */
38578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    public static void dimClockView(boolean dim, View clockView) {
38678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        Paint paint = new Paint();
38778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        paint.setColor(Color.WHITE);
38878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        paint.setColorFilter(new PorterDuffColorFilter(
38978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                        (dim ? 0x60FFFFFF : 0xC0FFFFFF),
39078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                PorterDuff.Mode.MULTIPLY));
39178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        clockView.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
39278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    }
39378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
39478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    /** Clock views can call this to refresh their alarm to the next upcoming value. **/
395b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson    public static void refreshAlarm(Context context, View clock) {
39678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        String nextAlarm = Settings.System.getString(context.getContentResolver(),
39778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                Settings.System.NEXT_ALARM_FORMATTED);
39878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        TextView nextAlarmView;
399b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson        nextAlarmView = (TextView) clock.findViewById(R.id.nextAlarm);
40078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        if (!TextUtils.isEmpty(nextAlarm) && nextAlarmView != null) {
40178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            nextAlarmView.setText(
40278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    context.getString(R.string.control_set_alarm_with_existing, nextAlarm));
40378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            nextAlarmView.setContentDescription(context.getResources().getString(
40478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein                    R.string.next_alarm_description, nextAlarm));
40578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            nextAlarmView.setVisibility(View.VISIBLE);
40678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        } else  {
40778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            nextAlarmView.setVisibility(View.GONE);
40878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        }
40978b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    }
41078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
41178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    /** Clock views can call this to refresh their date. **/
412b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson    public static void updateDate(
413b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson            String dateFormat, String dateFormatForAccessibility, View clock) {
41478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        Calendar cal = Calendar.getInstance();
41578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        cal.setTimeInMillis(System.currentTimeMillis());
41678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
41778b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        CharSequence newDate = DateFormat.format(dateFormat, cal);
41878b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        TextView dateDisplay;
419b41f177aef12a5aa5ec43057535f5deacf98a881Isaac Katzenelson        dateDisplay = (TextView) clock.findViewById(R.id.date);
42078b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        if (dateDisplay != null) {
42178b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            dateDisplay.setVisibility(View.VISIBLE);
42278b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            dateDisplay.setText(newDate);
42378b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein            dateDisplay.setContentDescription(DateFormat.format(dateFormatForAccessibility, cal));
42478b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein        }
42578b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein    }
42678b8e1513e24c58ffea6ee4edbebdce85c248f6fSam Blitzstein
427d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson    public static CityObj[] loadCitiesDataBase(Context c) {
428d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson        final Collator collator = Collator.getInstance();
429d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson        Resources r = c.getResources();
430d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson        // Read strings array of name,timezone, id
431d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson        // make sure the list are the same length
432d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        String[] cities = r.getStringArray(R.array.cities_names);
433d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        String[] timezones = r.getStringArray(R.array.cities_tz);
434d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        String[] ids = r.getStringArray(R.array.cities_id);
435d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson        if (cities.length != timezones.length || ids.length != cities.length) {
436d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson            Log.wtf("City lists sizes are not the same, cannot use the data");
437d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson            return null;
438d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        }
439d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        CityObj[] tempList = new CityObj[cities.length];
440d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        for (int i = 0; i < cities.length; i++) {
441d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson            tempList[i] = new CityObj(cities[i], timezones[i], ids[i]);
442d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        }
443d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        // Sort alphabetically
444d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson        Arrays.sort(tempList, new Comparator<CityObj> () {
445d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson            @Override
446d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson            public int compare(CityObj c1, CityObj c2) {
447d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson                Comparator<CityObj> mCollator;
448d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson                return collator.compare(c1.mCityName, c2.mCityName);
449d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson            }
450d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson        });
451d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson        return tempList;
452d4bbc122b90c63c5906ad32c4652b72c9409fd44Isaac Katzenelson    }
453d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson
454d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson    public static String getCityName(CityObj city, CityObj dbCity) {
455d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson        return (city.mCityId == null || dbCity == null) ? city.mCityName : dbCity.mCityName;
456d851e8a4b134028bd12f509312d31664e4c826ddIsaac Katzenelson    }
457d2f8c51aba02f5e8cbbf82234ff453f305fba759Isaac Katzenelson}
458