OSDN Git Service

Automatic translation import
[android-x86/packages-apps-Eleven.git] / src / com / cyngn / eleven / MediaButtonIntentReceiver.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project Licensed under the Apache
3  * License, Version 2.0 (the "License"); you may not use this file except in
4  * compliance with the License. You may obtain a copy of the License at
5  * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
6  * or agreed to in writing, software distributed under the License is
7  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8  * KIND, either express or implied. See the License for the specific language
9  * governing permissions and limitations under the License.
10  */
11
12 package com.cyngn.eleven;
13
14 import android.content.BroadcastReceiver;
15 import android.content.Context;
16 import android.content.Intent;
17 import android.media.AudioManager;
18 import android.os.Handler;
19 import android.os.Message;
20 import android.os.PowerManager;
21 import android.os.PowerManager.WakeLock;
22 import android.support.v4.content.WakefulBroadcastReceiver;
23 import android.util.Log;
24 import android.view.KeyEvent;
25
26 import com.cyngn.eleven.ui.activities.HomeActivity;
27
28 /**
29  * Used to control headset playback.
30  *   Single press: pause/resume
31  *   Double press: next track
32  *   Triple press: previous track
33  *   Long press: voice search
34  */
35 public class MediaButtonIntentReceiver extends WakefulBroadcastReceiver {
36     private static final boolean DEBUG = false;
37     private static final String TAG = "MediaButtonIntentReceiver";
38
39     private static final int MSG_LONGPRESS_TIMEOUT = 1;
40     private static final int MSG_HEADSET_DOUBLE_CLICK_TIMEOUT = 2;
41
42     private static final int LONG_PRESS_DELAY = 1000;
43     private static final int DOUBLE_CLICK = 800;
44
45     private static WakeLock mWakeLock = null;
46     private static int mClickCounter = 0;
47     private static long mLastClickTime = 0;
48     private static boolean mDown = false;
49     private static boolean mLaunched = false;
50
51     private static Handler mHandler = new Handler() {
52
53         /**
54          * {@inheritDoc}
55          */
56         @Override
57         public void handleMessage(final Message msg) {
58             switch (msg.what) {
59                 case MSG_LONGPRESS_TIMEOUT:
60                     if (DEBUG) Log.v(TAG, "Handling longpress timeout, launched " + mLaunched);
61                     if (!mLaunched) {
62                         final Context context = (Context)msg.obj;
63                         final Intent i = new Intent();
64                         i.setClass(context, HomeActivity.class);
65                         i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
66                         context.startActivity(i);
67                         mLaunched = true;
68                     }
69                     break;
70
71                 case MSG_HEADSET_DOUBLE_CLICK_TIMEOUT:
72                     final int clickCount = msg.arg1;
73                     final String command;
74
75                     if (DEBUG) Log.v(TAG, "Handling headset click, count = " + clickCount);
76                     switch (clickCount) {
77                         case 1: command = MusicPlaybackService.CMDTOGGLEPAUSE; break;
78                         case 2: command = MusicPlaybackService.CMDNEXT; break;
79                         case 3: command = MusicPlaybackService.CMDPREVIOUS; break;
80                         default: command = null; break;
81                     }
82
83                     if (command != null) {
84                         final Context context = (Context)msg.obj;
85                         startService(context, command);
86                     }
87                     break;
88             }
89             releaseWakeLockIfHandlerIdle();
90         }
91     };
92
93     /**
94      * {@inheritDoc}
95      */
96     @Override
97     public void onReceive(final Context context, final Intent intent) {
98         if (DEBUG) Log.v(TAG, "Received intent: " + intent);
99         final String intentAction = intent.getAction();
100         if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction)) {
101             startService(context, MusicPlaybackService.CMDPAUSE);
102         } else if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
103             final KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
104             if (event == null) {
105                 return;
106             }
107
108             final int keycode = event.getKeyCode();
109             final int action = event.getAction();
110             final long eventtime = event.getEventTime();
111
112             String command = null;
113             switch (keycode) {
114                 case KeyEvent.KEYCODE_MEDIA_STOP:
115                     command = MusicPlaybackService.CMDSTOP;
116                     break;
117                 case KeyEvent.KEYCODE_HEADSETHOOK:
118                 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
119                     command = MusicPlaybackService.CMDTOGGLEPAUSE;
120                     break;
121                 case KeyEvent.KEYCODE_MEDIA_NEXT:
122                     command = MusicPlaybackService.CMDNEXT;
123                     break;
124                 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
125                     command = MusicPlaybackService.CMDPREVIOUS;
126                     break;
127                 case KeyEvent.KEYCODE_MEDIA_PAUSE:
128                     command = MusicPlaybackService.CMDPAUSE;
129                     break;
130                 case KeyEvent.KEYCODE_MEDIA_PLAY:
131                     command = MusicPlaybackService.CMDPLAY;
132                     break;
133             }
134             if (command != null) {
135                 if (action == KeyEvent.ACTION_DOWN) {
136                     if (mDown) {
137                         if (MusicPlaybackService.CMDTOGGLEPAUSE.equals(command)
138                                 || MusicPlaybackService.CMDPLAY.equals(command)) {
139                             if (mLastClickTime != 0
140                                     && eventtime - mLastClickTime > LONG_PRESS_DELAY) {
141                                 acquireWakeLockAndSendMessage(context,
142                                         mHandler.obtainMessage(MSG_LONGPRESS_TIMEOUT, context), 0);
143                             }
144                         }
145                     } else if (event.getRepeatCount() == 0) {
146                         // Only consider the first event in a sequence, not the repeat events,
147                         // so that we don't trigger in cases where the first event went to
148                         // a different app (e.g. when the user ends a phone call by
149                         // long pressing the headset button)
150
151                         // The service may or may not be running, but we need to send it
152                         // a command.
153                         if (keycode == KeyEvent.KEYCODE_HEADSETHOOK) {
154                             if (eventtime - mLastClickTime >= DOUBLE_CLICK) {
155                                 mClickCounter = 0;
156                             }
157
158                             mClickCounter++;
159                             if (DEBUG) Log.v(TAG, "Got headset click, count = " + mClickCounter);
160                             mHandler.removeMessages(MSG_HEADSET_DOUBLE_CLICK_TIMEOUT);
161
162                             Message msg = mHandler.obtainMessage(
163                                     MSG_HEADSET_DOUBLE_CLICK_TIMEOUT, mClickCounter, 0, context);
164
165                             long delay = mClickCounter < 3 ? DOUBLE_CLICK : 0;
166                             if (mClickCounter >= 3) {
167                                 mClickCounter = 0;
168                             }
169                             mLastClickTime = eventtime;
170                             acquireWakeLockAndSendMessage(context, msg, delay);
171                         } else {
172                             startService(context, command);
173                         }
174                         mLaunched = false;
175                         mDown = true;
176                     }
177                 } else {
178                     mHandler.removeMessages(MSG_LONGPRESS_TIMEOUT);
179                     mDown = false;
180                 }
181                 if (isOrderedBroadcast()) {
182                     abortBroadcast();
183                 }
184                 releaseWakeLockIfHandlerIdle();
185             }
186         }
187     }
188
189     private static void startService(Context context, String command) {
190         final Intent i = new Intent(context, MusicPlaybackService.class);
191         i.setAction(MusicPlaybackService.SERVICECMD);
192         i.putExtra(MusicPlaybackService.CMDNAME, command);
193         i.putExtra(MusicPlaybackService.FROM_MEDIA_BUTTON, true);
194         startWakefulService(context, i);
195     }
196
197     private static void acquireWakeLockAndSendMessage(Context context, Message msg, long delay) {
198         if (mWakeLock == null) {
199             Context appContext = context.getApplicationContext();
200             PowerManager pm = (PowerManager) appContext.getSystemService(Context.POWER_SERVICE);
201             mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Eleven headset button");
202             mWakeLock.setReferenceCounted(false);
203         }
204         if (DEBUG) Log.v(TAG, "Acquiring wake lock and sending " + msg.what);
205         // Make sure we don't indefinitely hold the wake lock under any circumstances
206         mWakeLock.acquire(10000);
207
208         mHandler.sendMessageDelayed(msg, delay);
209     }
210
211     private static void releaseWakeLockIfHandlerIdle() {
212         if (mHandler.hasMessages(MSG_LONGPRESS_TIMEOUT)
213                 || mHandler.hasMessages(MSG_HEADSET_DOUBLE_CLICK_TIMEOUT)) {
214             if (DEBUG) Log.v(TAG, "Handler still has messages pending, not releasing wake lock");
215             return;
216         }
217
218         if (mWakeLock != null) {
219             if (DEBUG) Log.v(TAG, "Releasing wake lock");
220             mWakeLock.release();
221             mWakeLock = null;
222         }
223     }
224 }