summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik <roboerik@android.com>2010-09-14 12:21:53 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-09-14 12:21:53 -0700
commitb92788aa040d0971b4e54589aef7675f34d96e5d (patch)
tree207c8d8912ff53fab753255016c6c2c3f12f993f
parent934516e10150874fd1db5ab9e0be3ae793441fd8 (diff)
parent71ad58c751eb12a500916556c41e704a93895801 (diff)
downloadframeworks_base-b92788aa040d0971b4e54589aef7675f34d96e5d.zip
frameworks_base-b92788aa040d0971b4e54589aef7675f34d96e5d.tar.gz
frameworks_base-b92788aa040d0971b4e54589aef7675f34d96e5d.tar.bz2
Merge "Adds time zone functionality into fw as a hidden api" into gingerbread
-rw-r--r--core/java/android/provider/Calendar.java74
-rw-r--r--core/java/android/util/CalendarUtils.java309
2 files changed, 383 insertions, 0 deletions
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index 9a09805..6355a9c 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -943,6 +943,80 @@ public final class Calendar {
}
/**
+ * CalendarCache stores some settings for calendar including the current
+ * time zone for the app. These settings are stored using a key/value
+ * scheme.
+ */
+ public interface CalendarCacheColumns {
+ /**
+ * The key for the setting. Keys are defined in CalendarChache in the
+ * Calendar provider.
+ * TODO Add keys to this file
+ */
+ public static final String KEY = "key";
+
+ /**
+ * The value of the given setting.
+ */
+ public static final String VALUE = "value";
+ }
+
+ public static class CalendarCache implements CalendarCacheColumns {
+ /**
+ * The URI to use for retrieving the properties from the Calendar db.
+ */
+ public static final Uri URI =
+ Uri.parse("content://" + AUTHORITY + "/properties");
+ public static final String[] POJECTION = { KEY, VALUE };
+
+ /**
+ * If updating a property, this must be provided as the selection. All
+ * other selections will fail. For queries this field can be omitted to
+ * retrieve all properties or used to query a single property. Valid
+ * keys include {@link #TIMEZONE_KEY_TYPE},
+ * {@link #TIMEZONE_KEY_INSTANCES}, and
+ * {@link #TIMEZONE_KEY_INSTANCES_PREVIOUS}, though the last one can
+ * only be read, not written.
+ */
+ public static final String WHERE = "key=?";
+
+ /**
+ * They key for updating the use of auto/home time zones in Calendar.
+ * Valid values are {@link #TIMEZONE_TYPE_AUTO} or
+ * {@link #TIMEZONE_TYPE_HOME}.
+ */
+ public static final String TIMEZONE_KEY_TYPE = "timezoneType";
+
+ /**
+ * The key for updating the time zone used by the provider when it
+ * generates the instances table. This should only be written if the
+ * type is set to {@link #TIMEZONE_TYPE_HOME}. A valid time zone id
+ * should be written to this field.
+ */
+ public static final String TIMEZONE_KEY_INSTANCES = "timezoneInstances";
+
+ /**
+ * The key for reading the last time zone set by the user. This should
+ * only be read by apps and it will be automatically updated whenever
+ * {@link #TIMEZONE_KEY_INSTANCES} is updated with
+ * {@link #TIMEZONE_TYPE_HOME} set.
+ */
+ public static final String TIMEZONE_KEY_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
+
+ /**
+ * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider
+ * should stay in sync with the device's time zone.
+ */
+ public static final String TIMEZONE_TYPE_AUTO = "auto";
+
+ /**
+ * The value to write to {@link #TIMEZONE_KEY_TYPE} if the provider
+ * should use a fixed time zone set by the user.
+ */
+ public static final String TIMEZONE_TYPE_HOME = "home";
+ }
+
+ /**
* A few Calendar globals are needed in the CalendarProvider for expanding
* the Instances table and these are all stored in the first (and only)
* row of the CalendarMetaData table.
diff --git a/core/java/android/util/CalendarUtils.java b/core/java/android/util/CalendarUtils.java
new file mode 100644
index 0000000..81709d7
--- /dev/null
+++ b/core/java/android/util/CalendarUtils.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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 android.util;
+
+import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.provider.Calendar.CalendarCache;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.text.format.Time;
+
+import java.util.Formatter;
+import java.util.HashSet;
+import java.util.Locale;
+
+/**
+ * A class containing utility methods related to Calendar apps.
+ *
+ * @hide
+ */
+public class CalendarUtils {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "CalendarUtils";
+
+ /**
+ * This class contains methods specific to reading and writing time zone
+ * values.
+ */
+ public static class TimeZoneUtils {
+ private static StringBuilder mSB = new StringBuilder(50);
+ private static Formatter mF = new Formatter(mSB, Locale.getDefault());
+ private volatile static boolean mFirstTZRequest = true;
+ private volatile static boolean mTZQueryInProgress = false;
+
+ private volatile static boolean mUseHomeTZ = false;
+ private volatile static String mHomeTZ = Time.getCurrentTimezone();
+
+ private static HashSet<Runnable> mTZCallbacks = new HashSet<Runnable>();
+ private static int mToken = 1;
+ private static AsyncTZHandler mHandler;
+
+ // The name of the shared preferences file. This name must be maintained for historical
+ // reasons, as it's what PreferenceManager assigned the first time the file was created.
+ private final String mPrefsName;
+
+ /**
+ * This is the key used for writing whether or not a home time zone should
+ * be used in the Calendar app to the Calendar Preferences.
+ */
+ public static final String KEY_HOME_TZ_ENABLED = "preferences_home_tz_enabled";
+ /**
+ * This is the key used for writing the time zone that should be used if
+ * home time zones are enabled for the Calendar app.
+ */
+ public static final String KEY_HOME_TZ = "preferences_home_tz";
+
+ /**
+ * This is a helper class for handling the async queries and updates for the
+ * time zone settings in Calendar.
+ */
+ private class AsyncTZHandler extends AsyncQueryHandler {
+ public AsyncTZHandler(ContentResolver cr) {
+ super(cr);
+ }
+
+ @Override
+ protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ synchronized (mTZCallbacks) {
+ boolean writePrefs = false;
+ // Check the values in the db
+ int keyColumn = cursor.getColumnIndexOrThrow(CalendarCache.KEY);
+ int valueColumn = cursor.getColumnIndexOrThrow(CalendarCache.VALUE);
+ while(cursor.moveToNext()) {
+ String key = cursor.getString(keyColumn);
+ String value = cursor.getString(valueColumn);
+ if (TextUtils.equals(key, CalendarCache.TIMEZONE_KEY_TYPE)) {
+ boolean useHomeTZ = !TextUtils.equals(
+ value, CalendarCache.TIMEZONE_TYPE_AUTO);
+ if (useHomeTZ != mUseHomeTZ) {
+ writePrefs = true;
+ mUseHomeTZ = useHomeTZ;
+ }
+ } else if (TextUtils.equals(
+ key, CalendarCache.TIMEZONE_KEY_INSTANCES_PREVIOUS)) {
+ if (!TextUtils.isEmpty(value) && !TextUtils.equals(mHomeTZ, value)) {
+ writePrefs = true;
+ mHomeTZ = value;
+ }
+ }
+ }
+ if (writePrefs) {
+ SharedPreferences prefs = getSharedPreferences((Context)cookie, mPrefsName);
+ // Write the prefs
+ setSharedPreference(prefs, KEY_HOME_TZ_ENABLED, mUseHomeTZ);
+ setSharedPreference(prefs, KEY_HOME_TZ, mHomeTZ);
+ }
+
+ mTZQueryInProgress = false;
+ for (Runnable callback : mTZCallbacks) {
+ if (callback != null) {
+ callback.run();
+ }
+ }
+ mTZCallbacks.clear();
+ }
+ }
+ }
+
+ /**
+ * The name of the file where the shared prefs for Calendar are stored
+ * must be provided. All activities within an app should provide the
+ * same preferences name or behavior may become erratic.
+ *
+ * @param prefsName
+ */
+ public TimeZoneUtils(String prefsName) {
+ mPrefsName = prefsName;
+ }
+
+ /**
+ * Formats a date or a time range according to the local conventions.
+ *
+ * This formats a date/time range using Calendar's time zone and the
+ * local conventions for the region of the device.
+ *
+ * @param context the context is required only if the time is shown
+ * @param startMillis the start time in UTC milliseconds
+ * @param endMillis the end time in UTC milliseconds
+ * @param flags a bit mask of options See
+ * {@link DateUtils#formatDateRange(Context, Formatter, long, long, int, String) formatDateRange}
+ * @return a string containing the formatted date/time range.
+ */
+ public String formatDateRange(Context context, long startMillis,
+ long endMillis, int flags) {
+ String date;
+ synchronized (mSB) {
+ mSB.setLength(0);
+ date = DateUtils.formatDateRange(context, mF, startMillis, endMillis, flags,
+ getTimeZone(context, null)).toString();
+ }
+ return date;
+ }
+
+ /**
+ * Writes a new home time zone to the db.
+ *
+ * Updates the home time zone in the db asynchronously and updates
+ * the local cache. Sending a time zone of
+ * {@link CalendarCache#TIMEZONE_TYPE_AUTO} will cause it to be set
+ * to the device's time zone. null or empty tz will be ignored.
+ *
+ * @param context The calling activity
+ * @param timeZone The time zone to set Calendar to, or
+ * {@link CalendarCache#TIMEZONE_TYPE_AUTO}
+ */
+ public void setTimeZone(Context context, String timeZone) {
+ if (TextUtils.isEmpty(timeZone)) {
+ if (DEBUG) {
+ Log.d(TAG, "Empty time zone, nothing to be done.");
+ }
+ return;
+ }
+ boolean updatePrefs = false;
+ synchronized (mTZCallbacks) {
+ if (CalendarCache.TIMEZONE_TYPE_AUTO.equals(timeZone)) {
+ if (mUseHomeTZ) {
+ updatePrefs = true;
+ }
+ mUseHomeTZ = false;
+ } else {
+ if (!mUseHomeTZ || !TextUtils.equals(mHomeTZ, timeZone)) {
+ updatePrefs = true;
+ }
+ mUseHomeTZ = true;
+ mHomeTZ = timeZone;
+ }
+ }
+ if (updatePrefs) {
+ // Write the prefs
+ SharedPreferences prefs = getSharedPreferences(context, mPrefsName);
+ setSharedPreference(prefs, KEY_HOME_TZ_ENABLED, mUseHomeTZ);
+ setSharedPreference(prefs, KEY_HOME_TZ, mHomeTZ);
+
+ // Update the db
+ ContentValues values = new ContentValues();
+ if (mHandler == null) {
+ mHandler = new AsyncTZHandler(context.getContentResolver());
+ }
+
+ mHandler.cancelOperation(mToken);
+
+ // skip 0 so query can use it
+ if (++mToken == 0) {
+ mToken = 1;
+ }
+
+ // Write the use home tz setting
+ String[] selArgs = new String[] { CalendarCache.TIMEZONE_KEY_TYPE };
+ values.put(CalendarCache.VALUE, mUseHomeTZ ? CalendarCache.TIMEZONE_TYPE_HOME
+ : CalendarCache.TIMEZONE_TYPE_AUTO);
+ mHandler.startUpdate(mToken, null, CalendarCache.URI, values, CalendarCache.WHERE,
+ selArgs);
+
+ // If using a home tz write it to the db
+ if (mUseHomeTZ) {
+ selArgs[0] = CalendarCache.TIMEZONE_KEY_INSTANCES;
+ values.clear();
+ values.put(CalendarCache.VALUE, mHomeTZ);
+ mHandler.startUpdate(
+ mToken, null, CalendarCache.URI, values, CalendarCache.WHERE, selArgs);
+ }
+ }
+ }
+
+ /**
+ * Gets the time zone that Calendar should be displayed in
+ *
+ * This is a helper method to get the appropriate time zone for Calendar. If this
+ * is the first time this method has been called it will initiate an asynchronous
+ * query to verify that the data in preferences is correct. The callback supplied
+ * will only be called if this query returns a value other than what is stored in
+ * preferences and should cause the calling activity to refresh anything that
+ * depends on calling this method.
+ *
+ * @param context The calling activity
+ * @param callback The runnable that should execute if a query returns new values
+ * @return The string value representing the time zone Calendar should display
+ */
+ public String getTimeZone(Context context, Runnable callback) {
+ synchronized (mTZCallbacks){
+ if (mFirstTZRequest) {
+ mTZQueryInProgress = true;
+ mFirstTZRequest = false;
+
+ SharedPreferences prefs = getSharedPreferences(context, mPrefsName);
+ mUseHomeTZ = prefs.getBoolean(KEY_HOME_TZ_ENABLED, false);
+ mHomeTZ = prefs.getString(KEY_HOME_TZ, Time.getCurrentTimezone());
+
+ // When the async query returns it should synchronize on
+ // mTZCallbacks, update mUseHomeTZ, mHomeTZ, and the
+ // preferences, set mTZQueryInProgress to false, and call all
+ // the runnables in mTZCallbacks.
+ if (mHandler == null) {
+ mHandler = new AsyncTZHandler(context.getContentResolver());
+ }
+ mHandler.startQuery(0, context, CalendarCache.URI, CalendarCache.POJECTION,
+ null, null, null);
+ }
+ if (mTZQueryInProgress) {
+ mTZCallbacks.add(callback);
+ }
+ }
+ return mUseHomeTZ ? mHomeTZ : Time.getCurrentTimezone();
+ }
+ }
+
+ /**
+ * A helper method for writing a String value to the preferences
+ * asynchronously.
+ *
+ * @param context A context with access to the correct preferences
+ * @param key The preference to write to
+ * @param value The value to write
+ */
+ public static void setSharedPreference(SharedPreferences prefs, String key, String value) {
+// SharedPreferences prefs = getSharedPreferences(context);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(key, value);
+ editor.apply();
+ }
+
+ /**
+ * A helper method for writing a boolean value to the preferences
+ * asynchronously.
+ *
+ * @param context A context with access to the correct preferences
+ * @param key The preference to write to
+ * @param value The value to write
+ */
+ public static void setSharedPreference(SharedPreferences prefs, String key, boolean value) {
+// SharedPreferences prefs = getSharedPreferences(context, prefsName);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(key, value);
+ editor.apply();
+ }
+
+ /** Return a properly configured SharedPreferences instance */
+ public static SharedPreferences getSharedPreferences(Context context, String prefsName) {
+ return context.getSharedPreferences(prefsName, Context.MODE_PRIVATE);
+ }
+}