OSDN Git Service

Re-schedule screen saver mode when returning to normal.
[android-x86/packages-apps-DeskClock.git] / src / com / android / deskclock / DeskClock.java
index 0cb23c8..cfb599e 100644 (file)
@@ -41,6 +41,7 @@ import android.os.SystemClock;
 import android.os.PowerManager;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.text.format.DateFormat;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -74,8 +75,6 @@ import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.Locale;
@@ -89,18 +88,19 @@ public class DeskClock extends Activity {
 
     private static final String LOG_TAG = "DeskClock";
 
-    // Intent used to start the music player.
-    private static final String MUSIC_NOW_PLAYING = "com.android.music.PLAYBACK_VIEWER";
+    // Package ID of the music player.
+    private static final String MUSIC_PACKAGE_ID = "com.android.music";
 
+    // Alarm action for midnight (so we can update the date display).
     private static final String ACTION_MIDNIGHT = "com.android.deskclock.MIDNIGHT";
 
     // Interval between polls of the weather widget. Its refresh period is
     // likely to be much longer (~3h), but we want to pick up any changes
     // within 5 minutes.
-    private final long FETCH_WEATHER_DELAY = 5 * 60 * 1000; // 5 min
+    private final long QUERY_WEATHER_DELAY = 5 * 60 * 1000; // 5 min
 
     // Delay before engaging the burn-in protection mode (green-on-black).
-    private final long SCREEN_SAVER_TIMEOUT = 10 * 60 * 1000; // 10 min
+    private final long SCREEN_SAVER_TIMEOUT = 5* 60 * 1000; // 10 min
 
     // Repositioning delay in screen saver.
     private final long SCREEN_SAVER_MOVE_DELAY = 60 * 1000; // 1 min
@@ -109,8 +109,12 @@ public class DeskClock extends Activity {
     private final int SCREEN_SAVER_COLOR = 0xFF308030;
     private final int SCREEN_SAVER_COLOR_DIM = 0xFF183018;
 
+    // Opacity of black layer between clock display and wallpaper.
+    private final float DIM_BEHIND_AMOUNT_NORMAL = 0.4f;
+    private final float DIM_BEHIND_AMOUNT_DIMMED = 0.7f; // higher contrast when display dimmed
+
     // Internal message IDs.
-    private final int FETCH_WEATHER_DATA_MSG     = 0x1000;
+    private final int QUERY_WEATHER_DATA_MSG     = 0x1000;
     private final int UPDATE_WEATHER_DISPLAY_MSG = 0x1001;
     private final int SCREEN_SAVER_TIMEOUT_MSG   = 0x2000;
     private final int SCREEN_SAVER_MOVE_MSG      = 0x2001;
@@ -130,6 +134,8 @@ public class DeskClock extends Activity {
             "description",
         };
 
+    private static final String ACTION_GENIE_REFRESH = "com.google.android.apps.genie.REFRESH";
+
     // State variables follow.
     private DigitalClock mTime;
     private TextView mDate;
@@ -154,16 +160,12 @@ public class DeskClock extends Activity {
     private boolean mDimmed = false;
     private boolean mScreenSaverMode = false;
 
-    private DateFormat mDateFormat;
+    private String mDateFormat;
 
     private int mBatteryLevel = -1;
     private boolean mPluggedIn = false;
 
-    private boolean mInDock = false;
-
-    private int mIdleTimeoutEpoch = 0;
-
-    private boolean mWeatherFetchScheduled = false;
+    private boolean mLaunchedFromDock = false;
 
     private Random mRNG;
 
@@ -179,6 +181,16 @@ public class DeskClock extends Activity {
                 handleBatteryUpdate(
                     intent.getIntExtra("status", BATTERY_STATUS_UNKNOWN),
                     intent.getIntExtra("level", 0));
+            } else if (Intent.ACTION_DOCK_EVENT.equals(action)) {
+                int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, -1);
+                if (DEBUG) Log.d(LOG_TAG, "ACTION_DOCK_EVENT, state=" + state);
+                if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                    if (mLaunchedFromDock) {
+                        // moveTaskToBack(false);
+                        finish();
+                    }
+                    mLaunchedFromDock = false;
+                }
             }
         }
     };
@@ -186,17 +198,13 @@ public class DeskClock extends Activity {
     private final Handler mHandy = new Handler() {
         @Override
         public void handleMessage(Message m) {
-            if (m.what == FETCH_WEATHER_DATA_MSG) {
-                if (!mWeatherFetchScheduled) return;
-                mWeatherFetchScheduled = false;
-                new Thread() { public void run() { fetchWeatherData(); } }.start();
-                scheduleWeatherFetchDelayed(FETCH_WEATHER_DELAY);
+            if (m.what == QUERY_WEATHER_DATA_MSG) {
+                new Thread() { public void run() { queryWeatherData(); } }.start();
+                scheduleWeatherQueryDelayed(QUERY_WEATHER_DELAY);
             } else if (m.what == UPDATE_WEATHER_DISPLAY_MSG) {
                 updateWeatherDisplay();
             } else if (m.what == SCREEN_SAVER_TIMEOUT_MSG) {
-                if (m.arg1 == mIdleTimeoutEpoch) {
-                    saveScreen();
-                }
+                saveScreen();
             } else if (m.what == SCREEN_SAVER_MOVE_MSG) {
                 moveScreenSaver();
             }
@@ -210,14 +218,14 @@ public class DeskClock extends Activity {
     private void moveScreenSaverTo(int x, int y) {
         if (!mScreenSaverMode) return;
 
-        final View time_date = findViewById(R.id.time_date);
+        final View saver_view = findViewById(R.id.saver_view);
 
         DisplayMetrics metrics = new DisplayMetrics();
         getWindowManager().getDefaultDisplay().getMetrics(metrics);
 
         if (x < 0 || y < 0) {
-            int myWidth = time_date.getMeasuredWidth();
-            int myHeight = time_date.getMeasuredHeight();
+            int myWidth = saver_view.getMeasuredWidth();
+            int myHeight = saver_view.getMeasuredHeight();
             x = (int)(mRNG.nextFloat()*(metrics.widthPixels - myWidth));
             y = (int)(mRNG.nextFloat()*(metrics.heightPixels - myHeight));
         }
@@ -225,7 +233,7 @@ public class DeskClock extends Activity {
         if (DEBUG) Log.d(LOG_TAG, String.format("screen saver: %d: jumping to (%d,%d)",
                 System.currentTimeMillis(), x, y));
 
-        time_date.setLayoutParams(new AbsoluteLayout.LayoutParams(
+        saver_view.setLayoutParams(new AbsoluteLayout.LayoutParams(
             ViewGroup.LayoutParams.WRAP_CONTENT,
             ViewGroup.LayoutParams.WRAP_CONTENT,
             x,
@@ -251,12 +259,25 @@ public class DeskClock extends Activity {
         win.setAttributes(winParams);
     }
 
+    private void scheduleScreenSaver() {
+        // reschedule screen saver
+        mHandy.removeMessages(SCREEN_SAVER_TIMEOUT_MSG);
+        mHandy.sendMessageDelayed(
+            Message.obtain(mHandy, SCREEN_SAVER_TIMEOUT_MSG),
+            SCREEN_SAVER_TIMEOUT);
+    }
+
     private void restoreScreen() {
         if (!mScreenSaverMode) return;
         if (DEBUG) Log.d(LOG_TAG, "restoreScreen");
         mScreenSaverMode = false;
         initViews();
         doDim(false); // restores previous dim mode
+        // policy: update weather info when returning from screen saver
+        if (mPluggedIn) requestWeatherDataFetch();
+
+        scheduleScreenSaver();
+
         refreshAll();
     }
 
@@ -284,15 +305,21 @@ public class DeskClock extends Activity {
 
         mTime = (DigitalClock) findViewById(R.id.time);
         mDate = (TextView) findViewById(R.id.date);
+        mNextAlarm = (TextView) findViewById(R.id.nextAlarm);
 
         final int color = mDimmed ? SCREEN_SAVER_COLOR_DIM : SCREEN_SAVER_COLOR;
 
         ((TextView)findViewById(R.id.timeDisplay)).setTextColor(color);
         ((TextView)findViewById(R.id.am_pm)).setTextColor(color);
         mDate.setTextColor(color);
+        mNextAlarm.setTextColor(color);
+        mNextAlarm.setCompoundDrawablesWithIntrinsicBounds(
+            getResources().getDrawable(mDimmed
+                ? R.drawable.ic_lock_idle_alarm_saver_dim
+                : R.drawable.ic_lock_idle_alarm_saver),
+            null, null, null);
 
         mBatteryDisplay =
-        mNextAlarm =
         mWeatherCurrentTemperature =
         mWeatherHighTemperature =
         mWeatherLowTemperature =
@@ -300,6 +327,7 @@ public class DeskClock extends Activity {
         mWeatherIcon = null;
 
         refreshDate();
+        refreshAlarm();
 
         moveScreenSaverTo(oldLoc[0], oldLoc[1]);
     }
@@ -310,35 +338,32 @@ public class DeskClock extends Activity {
             restoreScreen();
     }
 
+    // Tell the Genie widget to load new data from the network.
+    private void requestWeatherDataFetch() {
+        if (DEBUG) Log.d(LOG_TAG, "forcing the Genie widget to update weather now...");
+        sendBroadcast(new Intent(ACTION_GENIE_REFRESH).putExtra("requestWeather", true));
+        // update the display with any new data
+        scheduleWeatherQueryDelayed(5000);
+    }
+
     private boolean supportsWeather() {
         return (mGenieResources != null);
     }
 
-    private void scheduleWeatherFetchDelayed(long delay) {
-        if (mWeatherFetchScheduled) return;
+    private void scheduleWeatherQueryDelayed(long delay) {
+        // cancel any existing scheduled queries
+        unscheduleWeatherQuery();
 
         if (DEBUG) Log.d(LOG_TAG, "scheduling weather fetch message for " + delay + "ms from now");
 
-        mWeatherFetchScheduled = true;
-
-        mHandy.sendEmptyMessageDelayed(FETCH_WEATHER_DATA_MSG, delay);
+        mHandy.sendEmptyMessageDelayed(QUERY_WEATHER_DATA_MSG, delay);
     }
 
-    private void unscheduleWeatherFetch() {
-        mWeatherFetchScheduled = false;
+    private void unscheduleWeatherQuery() {
+        mHandy.removeMessages(QUERY_WEATHER_DATA_MSG);
     }
 
-    private static final boolean sCelsius;
-    static {
-        String cc = Locale.getDefault().getCountry().toLowerCase();
-        sCelsius = !("us".equals(cc) || "bz".equals(cc) || "jm".equals(cc));
-    }
-
-    private static int celsiusToLocal(int tempC) {
-        return sCelsius ? tempC : (int) Math.round(tempC * 1.8f + 32);
-    }
-
-    private void fetchWeatherData() {
+    private void queryWeatherData() {
         // if we couldn't load the weather widget's resources, we simply
         // assume it's not present on the device.
         if (mGenieResources == null) return;
@@ -382,11 +407,11 @@ public class DeskClock extends Activity {
             mWeatherIconDrawable = mGenieResources.getDrawable(cur.getInt(
                 cur.getColumnIndexOrThrow("iconResId")));
             mWeatherCurrentTemperatureString = String.format("%d\u00b0",
-                celsiusToLocal(cur.getInt(cur.getColumnIndexOrThrow("temperature"))));
+                (cur.getInt(cur.getColumnIndexOrThrow("temperature"))));
             mWeatherHighTemperatureString = String.format("%d\u00b0",
-                celsiusToLocal(cur.getInt(cur.getColumnIndexOrThrow("highTemperature"))));
+                (cur.getInt(cur.getColumnIndexOrThrow("highTemperature"))));
             mWeatherLowTemperatureString = String.format("%d\u00b0",
-                celsiusToLocal(cur.getInt(cur.getColumnIndexOrThrow("lowTemperature"))));
+                (cur.getInt(cur.getColumnIndexOrThrow("lowTemperature"))));
             mWeatherLocationString = cur.getString(
                 cur.getColumnIndexOrThrow("location"));
         } else {
@@ -395,7 +420,7 @@ public class DeskClock extends Activity {
             mWeatherIconDrawable = null;
             mWeatherHighTemperatureString = "";
             mWeatherLowTemperatureString = "";
-            mWeatherLocationString = "Weather data unavailable."; // TODO: internationalize
+            mWeatherLocationString = getString(R.string.weather_fetch_failure);
         }
 
         mHandy.sendEmptyMessage(UPDATE_WEATHER_DISPLAY_MSG);
@@ -403,7 +428,7 @@ public class DeskClock extends Activity {
 
     private void refreshWeather() {
         if (supportsWeather())
-            scheduleWeatherFetchDelayed(0);
+            scheduleWeatherQueryDelayed(0);
         updateWeatherDisplay(); // in case we have it cached
     }
 
@@ -422,6 +447,11 @@ public class DeskClock extends Activity {
         final boolean pluggedIn = (plugStatus == BATTERY_STATUS_CHARGING || plugStatus == BATTERY_STATUS_FULL);
         if (pluggedIn != mPluggedIn) {
             setWakeLock(pluggedIn);
+
+            if (pluggedIn) {
+                // policy: update weather info when attaching to power
+                requestWeatherDataFetch();
+            }
         }
         if (pluggedIn != mPluggedIn || batteryLevel != mBatteryLevel) {
             mBatteryLevel = batteryLevel;
@@ -447,7 +477,7 @@ public class DeskClock extends Activity {
     private void refreshDate() {
         final Date now = new Date();
         if (DEBUG) Log.d(LOG_TAG, "refreshing date..." + now);
-        mDate.setText(mDateFormat.format(now));
+        mDate.setText(DateFormat.format(mDateFormat, now));
     }
 
     private void refreshAlarm() {
@@ -487,7 +517,7 @@ public class DeskClock extends Activity {
 
         if (mDimmed) {
             winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
-            winParams.dimAmount = 0.67f; // pump up contrast in dim mode
+            winParams.dimAmount = DIM_BEHIND_AMOUNT_DIMMED;
 
             // show the window tint
             tintView.startAnimation(AnimationUtils.loadAnimation(this,
@@ -495,7 +525,7 @@ public class DeskClock extends Activity {
                      : R.anim.dim_instant));
         } else {
             winParams.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
-            winParams.dimAmount = 0.5f; // lower contrast in normal mode
+            winParams.dimAmount = DIM_BEHIND_AMOUNT_NORMAL;
 
             // hide the window tint
             tintView.startAnimation(AnimationUtils.loadAnimation(this,
@@ -507,70 +537,74 @@ public class DeskClock extends Activity {
     }
 
     @Override
+    public void onNewIntent(Intent newIntent) {
+        super.onNewIntent(newIntent);
+        if (DEBUG) Log.d(LOG_TAG, "onNewIntent with intent: " + newIntent);
+
+        // update our intent so that we can consult it to determine whether or
+        // not the most recent launch was via a dock event 
+        setIntent(newIntent);
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
-        if (DEBUG) Log.d(LOG_TAG, "onResume");
+        if (DEBUG) Log.d(LOG_TAG, "onResume with intent: " + getIntent());
 
         // reload the date format in case the user has changed settings
         // recently
-        final SimpleDateFormat dateFormat = (SimpleDateFormat)
-                java.text.DateFormat.getDateInstance(java.text.DateFormat.FULL);
-        // This is a little clumsy; we want to honor the locale's date format
-        // (rather than simply hardcoding "Weekday, Month Date") but
-        // DateFormat.FULL includes the year (at least, in enUS). So we lop
-        // that bit off if it's there; should have no effect on
-        // locale-specific date strings that look different.
-        mDateFormat = new SimpleDateFormat(dateFormat.toPattern()
-                    .replace(", yyyy", "")); // no year
+        mDateFormat = getString(com.android.internal.R.string.full_wday_month_day_no_year);
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_DATE_CHANGED);
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+        filter.addAction(Intent.ACTION_DOCK_EVENT);
         filter.addAction(ACTION_MIDNIGHT);
+        registerReceiver(mIntentReceiver, filter);
 
         Calendar today = Calendar.getInstance();
         today.add(Calendar.DATE, 1);
         mMidnightIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_MIDNIGHT), 0);
         AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
         am.setRepeating(AlarmManager.RTC, today.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mMidnightIntent);
-        registerReceiver(mIntentReceiver, filter);
 
+        // un-dim when resuming
+        mDimmed = false;
         doDim(false);
-        restoreScreen();
+
+        restoreScreen(); // disable screen saver
         refreshAll(); // will schedule periodic weather fetch
 
         setWakeLock(mPluggedIn);
 
-        mIdleTimeoutEpoch++;
-        mHandy.sendMessageDelayed(
-            Message.obtain(mHandy, SCREEN_SAVER_TIMEOUT_MSG, mIdleTimeoutEpoch, 0),
-            SCREEN_SAVER_TIMEOUT);
+        scheduleScreenSaver();
 
-        final boolean launchedFromDock 
+        final boolean launchedFromDock
             = getIntent().hasCategory(Intent.CATEGORY_DESK_DOCK);
 
-        if (supportsWeather() && launchedFromDock && !mInDock) {
+        if (supportsWeather() && launchedFromDock && !mLaunchedFromDock) {
+            // policy: fetch weather if launched via dock connection
             if (DEBUG) Log.d(LOG_TAG, "Device now docked; forcing weather to refresh right now");
-            sendBroadcast(
-                new Intent("com.google.android.apps.genie.REFRESH")
-                    .putExtra("requestWeather", true));
+            requestWeatherDataFetch();
         }
 
-        mInDock = launchedFromDock;
+        mLaunchedFromDock = launchedFromDock;
     }
 
     @Override
     public void onPause() {
         if (DEBUG) Log.d(LOG_TAG, "onPause");
 
-        // Turn off the screen saver. (But don't un-dim.)
+        // Turn off the screen saver and cancel any pending timeouts.
+        // (But don't un-dim.)
+        mHandy.removeMessages(SCREEN_SAVER_TIMEOUT_MSG);
         restoreScreen();
 
         // Other things we don't want to be doing in the background.
         unregisterReceiver(mIntentReceiver);
         AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
         am.cancel(mMidnightIntent);
-        unscheduleWeatherFetch();
+        unscheduleWeatherQuery();
 
         super.onPause();
     }
@@ -606,14 +640,17 @@ public class DeskClock extends Activity {
         mWeatherLocation = (TextView) findViewById(R.id.weather_location);
         mWeatherIcon = (ImageView) findViewById(R.id.weather_icon);
 
-        mNextAlarm = (TextView) findViewById(R.id.nextAlarm);
-
-        final ImageButton alarmButton = (ImageButton) findViewById(R.id.alarm_button);
-        alarmButton.setOnClickListener(new View.OnClickListener() {
+        final View.OnClickListener alarmClickListener = new View.OnClickListener() {
             public void onClick(View v) {
                 startActivity(new Intent(DeskClock.this, AlarmClock.class));
             }
-        });
+        };
+
+        mNextAlarm = (TextView) findViewById(R.id.nextAlarm);
+        mNextAlarm.setOnClickListener(alarmClickListener);
+
+        final ImageButton alarmButton = (ImageButton) findViewById(R.id.alarm_button);
+        alarmButton.setOnClickListener(alarmClickListener);
 
         final ImageButton galleryButton = (ImageButton) findViewById(R.id.gallery_button);
         galleryButton.setOnClickListener(new View.OnClickListener() {
@@ -622,7 +659,8 @@ public class DeskClock extends Activity {
                     startActivity(new Intent(
                         Intent.ACTION_VIEW,
                         android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
-                            .putExtra("slideshow", true));
+                            .putExtra("slideshow", true)
+                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP));
                 } catch (android.content.ActivityNotFoundException e) {
                     Log.e(LOG_TAG, "Couldn't launch image browser", e);
                 }
@@ -633,7 +671,12 @@ public class DeskClock extends Activity {
         musicButton.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 try {
-                    startActivity(new Intent(MUSIC_NOW_PLAYING));
+                    Intent musicAppQuery = getPackageManager()
+                        .getLaunchIntentForPackage(MUSIC_PACKAGE_ID)
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                    if (musicAppQuery != null) {
+                        startActivity(musicAppQuery);
+                    }
                 } catch (android.content.ActivityNotFoundException e) {
                     Log.e(LOG_TAG, "Couldn't launch music browser", e);
                 }
@@ -645,6 +688,7 @@ public class DeskClock extends Activity {
             public void onClick(View v) {
                 startActivity(
                     new Intent(Intent.ACTION_MAIN)
+                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP)
                         .addCategory(Intent.CATEGORY_HOME));
             }
         });
@@ -669,7 +713,9 @@ public class DeskClock extends Activity {
             public void onClick(View v) {
                 if (!supportsWeather()) return;
 
-                Intent genieAppQuery = getPackageManager().getLaunchIntentForPackage(GENIE_PACKAGE_ID);
+                Intent genieAppQuery = getPackageManager()
+                    .getLaunchIntentForPackage(GENIE_PACKAGE_ID)
+                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
                 if (genieAppQuery != null) {
                     startActivity(genieAppQuery);
                 }
@@ -692,6 +738,9 @@ public class DeskClock extends Activity {
         if (item.getItemId() == R.id.menu_item_alarms) {
             startActivity(new Intent(DeskClock.this, AlarmClock.class));
             return true;
+        } else if (item.getItemId() == R.id.menu_item_add_alarm) {
+            AlarmClock.addNewAlarm(this);
+            return true;
         }
         return false;
     }