Home | History | Annotate | Download | only in alarms
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.deskclock.alarms;
     18 
     19 import android.app.Activity;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.content.pm.ActivityInfo;
     25 import android.content.res.Configuration;
     26 import android.os.Bundle;
     27 import android.os.Handler;
     28 import android.os.Message;
     29 import android.preference.PreferenceManager;
     30 import android.view.KeyEvent;
     31 import android.view.LayoutInflater;
     32 import android.view.View;
     33 import android.view.Window;
     34 import android.view.WindowManager;
     35 import android.widget.TextClock;
     36 import android.widget.TextView;
     37 
     38 import com.android.deskclock.Log;
     39 import com.android.deskclock.R;
     40 import com.android.deskclock.SettingsActivity;
     41 import com.android.deskclock.Utils;
     42 import com.android.deskclock.provider.AlarmInstance;
     43 import com.android.deskclock.widget.multiwaveview.GlowPadView;
     44 
     45 /**
     46  * Alarm activity that pops up a visible indicator when the alarm goes off.
     47  */
     48 public class AlarmActivity extends Activity {
     49     // AlarmActivity listens for this broadcast intent, so that other applications
     50     // can snooze the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION).
     51     public static final String ALARM_SNOOZE_ACTION = "com.android.deskclock.ALARM_SNOOZE";
     52 
     53     // AlarmActivity listens for this broadcast intent, so that other applications
     54     // can dismiss the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION).
     55     public static final String ALARM_DISMISS_ACTION = "com.android.deskclock.ALARM_DISMISS";
     56 
     57     // Controller for GlowPadView.
     58     private class GlowPadController extends Handler implements GlowPadView.OnTriggerListener {
     59         private static final int PING_MESSAGE_WHAT = 101;
     60         private static final long PING_AUTO_REPEAT_DELAY_MSEC = 1200;
     61 
     62         public void startPinger() {
     63             sendEmptyMessage(PING_MESSAGE_WHAT);
     64         }
     65 
     66         public void stopPinger() {
     67             removeMessages(PING_MESSAGE_WHAT);
     68         }
     69 
     70         @Override
     71         public void handleMessage(Message msg) {
     72             ping();
     73             sendEmptyMessageDelayed(PING_MESSAGE_WHAT, PING_AUTO_REPEAT_DELAY_MSEC);
     74         }
     75 
     76         @Override
     77         public void onGrabbed(View v, int handle) {
     78             stopPinger();
     79         }
     80 
     81         @Override
     82         public void onReleased(View v, int handle) {
     83             startPinger();
     84 
     85         }
     86 
     87         @Override
     88         public void onTrigger(View v, int target) {
     89             switch (mGlowPadView.getResourceIdForTarget(target)) {
     90                 case R.drawable.ic_alarm_alert_snooze:
     91                     Log.v("AlarmActivity - GlowPad snooze trigger");
     92                     snooze();
     93                     break;
     94 
     95                 case R.drawable.ic_alarm_alert_dismiss:
     96                     Log.v("AlarmActivity - GlowPad dismiss trigger");
     97                     dismiss();
     98                     break;
     99                 default:
    100                     // Code should never reach here.
    101                     Log.e("Trigger detected on unhandled resource. Skipping.");
    102             }
    103         }
    104 
    105         @Override
    106         public void onGrabbedStateChange(View v, int handle) {
    107         }
    108 
    109         @Override
    110         public void onFinishFinalAnimation() {
    111         }
    112     }
    113 
    114     private AlarmInstance mInstance;
    115     private int mVolumeBehavior;
    116     private GlowPadView mGlowPadView;
    117     private GlowPadController glowPadController = new GlowPadController();
    118     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
    119         @Override
    120         public void onReceive(Context context, Intent intent) {
    121             String action = intent.getAction();
    122             Log.v("AlarmActivity - Broadcast Receiver - " + action);
    123             if (action.equals(ALARM_SNOOZE_ACTION)) {
    124                 snooze();
    125             } else if (action.equals(ALARM_DISMISS_ACTION)) {
    126                 dismiss();
    127             } else if (action.equals(AlarmService.ALARM_DONE_ACTION)) {
    128                 finish();
    129             } else {
    130                 Log.i("Unknown broadcast in AlarmActivity: " + action);
    131             }
    132         }
    133     };
    134 
    135     private void snooze() {
    136         AlarmStateManager.setSnoozeState(this, mInstance);
    137     }
    138 
    139     private void dismiss() {
    140         AlarmStateManager.setDismissState(this, mInstance);
    141     }
    142 
    143     @Override
    144     protected void onCreate(Bundle icicle) {
    145         super.onCreate(icicle);
    146 
    147         long instanceId = AlarmInstance.getId(getIntent().getData());
    148         mInstance = AlarmInstance.getInstance(this.getContentResolver(), instanceId);
    149         if (mInstance != null) {
    150             Log.v("Displaying alarm for instance: " + mInstance);
    151         } else {
    152             // The alarm got deleted before the activity got created, so just finish()
    153             Log.v("Error displaying alarm for intent: " + getIntent());
    154             finish();
    155             return;
    156         }
    157 
    158         // Get the volume/camera button behavior setting
    159         final String vol =
    160                 PreferenceManager.getDefaultSharedPreferences(this)
    161                 .getString(SettingsActivity.KEY_VOLUME_BEHAVIOR,
    162                         SettingsActivity.DEFAULT_VOLUME_BEHAVIOR);
    163         mVolumeBehavior = Integer.parseInt(vol);
    164 
    165         final Window win = getWindow();
    166         win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
    167                 WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
    168                 WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
    169                 WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
    170                 WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
    171 
    172         // In order to allow tablets to freely rotate and phones to stick
    173         // with "nosensor" (use default device orientation) we have to have
    174         // the manifest start with an orientation of unspecified" and only limit
    175         // to "nosensor" for phones. Otherwise we get behavior like in b/8728671
    176         // where tablets start off in their default orientation and then are
    177         // able to freely rotate.
    178         if (!getResources().getBoolean(R.bool.config_rotateAlarmAlert)) {
    179             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
    180         }
    181         updateLayout();
    182 
    183         // Register to get the alarm done/snooze/dismiss intent.
    184         IntentFilter filter = new IntentFilter(AlarmService.ALARM_DONE_ACTION);
    185         filter.addAction(ALARM_SNOOZE_ACTION);
    186         filter.addAction(ALARM_DISMISS_ACTION);
    187         registerReceiver(mReceiver, filter);
    188     }
    189 
    190 
    191     private void updateTitle() {
    192         final String titleText = mInstance.getLabelOrDefault(this);
    193         TextView tv = (TextView)findViewById(R.id.alertTitle);
    194         tv.setText(titleText);
    195         super.setTitle(titleText);
    196     }
    197 
    198     private void updateLayout() {
    199         final LayoutInflater inflater = LayoutInflater.from(this);
    200         final View view = inflater.inflate(R.layout.alarm_alert, null);
    201         view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
    202         setContentView(view);
    203         updateTitle();
    204         Utils.setTimeFormat((TextClock)(view.findViewById(R.id.digitalClock)),
    205                 (int)getResources().getDimension(R.dimen.bottom_text_size));
    206 
    207         // Setup GlowPadController
    208         mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
    209         mGlowPadView.setOnTriggerListener(glowPadController);
    210         glowPadController.startPinger();
    211     }
    212 
    213     private void ping() {
    214         mGlowPadView.ping();
    215     }
    216 
    217     @Override
    218     public void onConfigurationChanged(Configuration newConfig) {
    219         super.onConfigurationChanged(newConfig);
    220         updateLayout();
    221     }
    222 
    223     @Override
    224     protected void onResume() {
    225         super.onResume();
    226         glowPadController.startPinger();
    227     }
    228 
    229     @Override
    230     protected void onPause() {
    231         super.onPause();
    232         glowPadController.stopPinger();
    233     }
    234 
    235     @Override
    236     public void onDestroy() {
    237         super.onDestroy();
    238         unregisterReceiver(mReceiver);
    239     }
    240 
    241     @Override
    242     public void onBackPressed() {
    243         // Don't allow back to dismiss.
    244     }
    245 
    246     @Override
    247     public boolean dispatchKeyEvent(KeyEvent event) {
    248         // Do this on key down to handle a few of the system keys.
    249         Log.v("AlarmActivity - dispatchKeyEvent - " + event.getKeyCode());
    250         switch (event.getKeyCode()) {
    251             // Volume keys and camera keys dismiss the alarm
    252             case KeyEvent.KEYCODE_POWER:
    253             case KeyEvent.KEYCODE_VOLUME_UP:
    254             case KeyEvent.KEYCODE_VOLUME_DOWN:
    255             case KeyEvent.KEYCODE_VOLUME_MUTE:
    256             case KeyEvent.KEYCODE_CAMERA:
    257             case KeyEvent.KEYCODE_FOCUS:
    258                 if (event.getAction() == KeyEvent.ACTION_UP) {
    259                     switch (mVolumeBehavior) {
    260                         case 1:
    261                             snooze();
    262                             break;
    263 
    264                         case 2:
    265                             dismiss();
    266                             break;
    267 
    268                         default:
    269                             break;
    270                     }
    271                 }
    272                 return true;
    273             default:
    274                 break;
    275         }
    276         return super.dispatchKeyEvent(event);
    277     }
    278 }
    279