blob: 893562ed40a24f41eaba8e6c26f54bfcc73ce400 [file] [log] [blame]
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001/*
2 * Copyright (C) 2007 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
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080018
Jim Millerd6523da2012-10-21 16:47:02 -070019import android.app.Activity;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080020import android.content.Context;
Jim Miller39d4b062011-01-11 20:30:20 -080021import android.graphics.Canvas;
22import android.graphics.ColorFilter;
23import android.graphics.PixelFormat;
24import android.graphics.PorterDuff;
25import android.graphics.drawable.Drawable;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080026import android.media.AudioManager;
Jean-Michel Trivic6802222012-04-30 11:15:03 -070027import android.media.IAudioService;
28import android.os.RemoteException;
29import android.os.ServiceManager;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -080030import android.telephony.TelephonyManager;
Karl Rosaenad297342009-03-24 18:55:19 -070031import android.util.AttributeSet;
Jean-Michel Trivic6802222012-04-30 11:15:03 -070032import android.util.Log;
33import android.util.Slog;
Jim Miller838906b2012-10-19 18:41:25 -070034import android.view.KeyEvent;
35import android.widget.FrameLayout;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080036
37/**
Jim Millerdcb3d842012-08-23 19:18:12 -070038 * Base class for keyguard view. {@link #reset} is where you should
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080039 * reset the state of your view. Use the {@link KeyguardViewCallback} via
40 * {@link #getCallback()} to send information back (such as poking the wake lock,
41 * or finishing the keyguard).
42 *
43 * Handles intercepting of media keys that still work when the keyguard is
44 * showing.
45 */
Jim Miller838906b2012-10-19 18:41:25 -070046public abstract class KeyguardViewBase extends FrameLayout {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080047
Jim Miller39d4b062011-01-11 20:30:20 -080048 private static final int BACKGROUND_COLOR = 0x70000000;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080049 private AudioManager mAudioManager;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -080050 private TelephonyManager mTelephonyManager = null;
Jim Millerdcb3d842012-08-23 19:18:12 -070051 protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
52
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -080053 // Whether the volume keys should be handled by keyguard. If true, then
54 // they will be handled here for specific media types such as music, otherwise
55 // the audio service will bring up the volume dialog.
Amith Yamasani6243edd2011-12-05 19:58:48 -080056 private static final boolean KEYGUARD_MANAGES_VOLUME = true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080057
Jim Miller2928c9d2011-10-20 17:00:38 -070058 // This is a faster way to draw the background on devices without hardware acceleration
Jim Millerdcb3d842012-08-23 19:18:12 -070059 private static final Drawable mBackgroundDrawable = new Drawable() {
Jim Miller2928c9d2011-10-20 17:00:38 -070060 @Override
61 public void draw(Canvas canvas) {
62 canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
63 }
64
65 @Override
66 public void setAlpha(int alpha) {
67 }
68
69 @Override
70 public void setColorFilter(ColorFilter cf) {
71 }
72
73 @Override
74 public int getOpacity() {
75 return PixelFormat.TRANSLUCENT;
76 }
77 };
78
Jim Millerdcb3d842012-08-23 19:18:12 -070079 public KeyguardViewBase(Context context) {
80 this(context, null);
81 }
82
83 public KeyguardViewBase(Context context, AttributeSet attrs) {
84 super(context, attrs);
Jim Miller2928c9d2011-10-20 17:00:38 -070085 resetBackground();
86 }
Jim Miller39d4b062011-01-11 20:30:20 -080087
Jim Miller2928c9d2011-10-20 17:00:38 -070088 public void resetBackground() {
Jim Millerdcb3d842012-08-23 19:18:12 -070089 setBackground(mBackgroundDrawable);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080090 }
91
92 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080093 * Called when the screen turned off.
94 */
95 abstract public void onScreenTurnedOff();
96
97 /**
98 * Called when the screen turned on.
99 */
100 abstract public void onScreenTurnedOn();
101
102 /**
Brian Colonna4284e9d2011-09-28 12:08:58 -0400103 * Called when the view needs to be shown.
104 */
105 abstract public void show();
106
107 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800108 * Verify that the user can get past the keyguard securely. This is called,
109 * for example, when the phone disables the keyguard but then wants to launch
110 * something else that requires secure access.
111 *
112 * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
113 */
114 abstract public void verifyUnlock();
115
116 /**
117 * Called before this view is being removed.
118 */
119 abstract public void cleanUp();
120
Jeff Brownc7505bc2012-10-05 21:58:15 -0700121 /**
122 * Gets the desired user activity timeout in milliseconds, or -1 if the
123 * default should be used.
124 */
125 abstract public long getUserActivityTimeout();
126
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800127 @Override
128 public boolean dispatchKeyEvent(KeyEvent event) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800129 if (interceptMediaKey(event)) {
130 return true;
131 }
132 return super.dispatchKeyEvent(event);
133 }
134
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800135 /**
Marco Nelissen24d10562009-05-12 14:15:17 -0700136 * Allows the media keys to work when the keyguard is showing.
137 * The media keys should be of no interest to the actual keyguard view(s),
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800138 * so intercepting them here should not be of any harm.
139 * @param event The key event
140 * @return whether the event was consumed as a media key.
141 */
142 private boolean interceptMediaKey(KeyEvent event) {
143 final int keyCode = event.getKeyCode();
144 if (event.getAction() == KeyEvent.ACTION_DOWN) {
145 switch (keyCode) {
Marco Nelissena6face42010-10-25 10:21:59 -0700146 case KeyEvent.KEYCODE_MEDIA_PLAY:
147 case KeyEvent.KEYCODE_MEDIA_PAUSE:
Andy Stadler8b89d692009-04-10 16:24:49 -0700148 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
Jeff Brown4d396052010-10-29 21:50:21 -0700149 /* Suppress PLAY/PAUSE toggle when phone is ringing or
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800150 * in-call to avoid music playback */
151 if (mTelephonyManager == null) {
152 mTelephonyManager = (TelephonyManager) getContext().getSystemService(
153 Context.TELEPHONY_SERVICE);
154 }
155 if (mTelephonyManager != null &&
156 mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
157 return true; // suppress key event
158 }
Jeff Brown4d396052010-10-29 21:50:21 -0700159 case KeyEvent.KEYCODE_MUTE:
160 case KeyEvent.KEYCODE_HEADSETHOOK:
161 case KeyEvent.KEYCODE_MEDIA_STOP:
162 case KeyEvent.KEYCODE_MEDIA_NEXT:
163 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
164 case KeyEvent.KEYCODE_MEDIA_REWIND:
165 case KeyEvent.KEYCODE_MEDIA_RECORD:
Jaekyun Seokbfdad8e2013-07-08 13:53:21 +0900166 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
167 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700168 handleMediaKeyEvent(event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800169 return true;
170 }
171
172 case KeyEvent.KEYCODE_VOLUME_UP:
Jeff Brownb0418da2010-11-01 15:24:01 -0700173 case KeyEvent.KEYCODE_VOLUME_DOWN:
174 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -0800175 if (KEYGUARD_MANAGES_VOLUME) {
176 synchronized (this) {
177 if (mAudioManager == null) {
178 mAudioManager = (AudioManager) getContext().getSystemService(
179 Context.AUDIO_SERVICE);
180 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800181 }
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700182 // Volume buttons should only function for music (local or remote).
183 // TODO: Actually handle MUTE.
184 mAudioManager.adjustLocalOrRemoteStreamVolume(
185 AudioManager.STREAM_MUSIC,
186 keyCode == KeyEvent.KEYCODE_VOLUME_UP
187 ? AudioManager.ADJUST_RAISE
188 : AudioManager.ADJUST_LOWER);
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -0800189 // Don't execute default volume behavior
190 return true;
191 } else {
192 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800193 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800194 }
195 }
196 } else if (event.getAction() == KeyEvent.ACTION_UP) {
197 switch (keyCode) {
198 case KeyEvent.KEYCODE_MUTE:
Jeff Brown4d396052010-10-29 21:50:21 -0700199 case KeyEvent.KEYCODE_HEADSETHOOK:
200 case KeyEvent.KEYCODE_MEDIA_PLAY:
201 case KeyEvent.KEYCODE_MEDIA_PAUSE:
202 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
203 case KeyEvent.KEYCODE_MEDIA_STOP:
204 case KeyEvent.KEYCODE_MEDIA_NEXT:
205 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
206 case KeyEvent.KEYCODE_MEDIA_REWIND:
207 case KeyEvent.KEYCODE_MEDIA_RECORD:
Jaekyun Seokbfdad8e2013-07-08 13:53:21 +0900208 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
209 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700210 handleMediaKeyEvent(event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800211 return true;
212 }
213 }
214 }
215 return false;
216 }
217
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700218 void handleMediaKeyEvent(KeyEvent keyEvent) {
219 IAudioService audioService = IAudioService.Stub.asInterface(
220 ServiceManager.checkService(Context.AUDIO_SERVICE));
221 if (audioService != null) {
222 try {
223 audioService.dispatchMediaKeyEvent(keyEvent);
224 } catch (RemoteException e) {
225 Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e);
226 }
227 } else {
228 Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event");
229 }
230 }
231
Joe Onorato4671ce52011-01-27 21:15:42 -0800232 @Override
233 public void dispatchSystemUiVisibilityChanged(int visibility) {
234 super.dispatchSystemUiVisibilityChanged(visibility);
Jim Millerd6523da2012-10-21 16:47:02 -0700235
236 if (!(mContext instanceof Activity)) {
237 setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
238 }
Joe Onorato4671ce52011-01-27 21:15:42 -0800239 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700240
241 public void setViewMediatorCallback(
242 KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
243 mViewMediatorCallback = viewMediatorCallback;
244 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800245}