KeyguardViewBase.java revision dcb3d84b82cc2448d04e73359a716581bfb657db
1/* 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 17package com.android.internal.policy.impl.keyguard; 18 19import android.content.Context; 20import android.graphics.Canvas; 21import android.graphics.ColorFilter; 22import android.graphics.PixelFormat; 23import android.graphics.PorterDuff; 24import android.graphics.drawable.Drawable; 25import android.media.AudioManager; 26import android.media.IAudioService; 27import android.os.RemoteException; 28import android.os.ServiceManager; 29import android.telephony.TelephonyManager; 30import android.view.KeyEvent; 31import android.widget.LinearLayout; 32import android.util.AttributeSet; 33import android.util.Log; 34import android.util.Slog; 35 36/** 37 * Base class for keyguard view. {@link #reset} is where you should 38 * reset the state of your view. Use the {@link KeyguardViewCallback} via 39 * {@link #getCallback()} to send information back (such as poking the wake lock, 40 * or finishing the keyguard). 41 * 42 * Handles intercepting of media keys that still work when the keyguard is 43 * showing. 44 */ 45public abstract class KeyguardViewBase extends LinearLayout { 46 47 private static final int BACKGROUND_COLOR = 0x70000000; 48 private AudioManager mAudioManager; 49 private TelephonyManager mTelephonyManager = null; 50 protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback; 51 52 // Whether the volume keys should be handled by keyguard. If true, then 53 // they will be handled here for specific media types such as music, otherwise 54 // the audio service will bring up the volume dialog. 55 private static final boolean KEYGUARD_MANAGES_VOLUME = true; 56 57 // This is a faster way to draw the background on devices without hardware acceleration 58 private static final Drawable mBackgroundDrawable = new Drawable() { 59 @Override 60 public void draw(Canvas canvas) { 61 canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC); 62 } 63 64 @Override 65 public void setAlpha(int alpha) { 66 } 67 68 @Override 69 public void setColorFilter(ColorFilter cf) { 70 } 71 72 @Override 73 public int getOpacity() { 74 return PixelFormat.TRANSLUCENT; 75 } 76 }; 77 78 public KeyguardViewBase(Context context) { 79 this(context, null); 80 } 81 82 public KeyguardViewBase(Context context, AttributeSet attrs) { 83 super(context, attrs); 84 resetBackground(); 85 } 86 87 public void resetBackground() { 88 setBackground(mBackgroundDrawable); 89 } 90 91 /** 92 * Called when you need to reset the state of your view. 93 */ 94 abstract public void reset(); 95 96 /** 97 * Called when the screen turned off. 98 */ 99 abstract public void onScreenTurnedOff(); 100 101 /** 102 * Called when the screen turned on. 103 */ 104 abstract public void onScreenTurnedOn(); 105 106 /** 107 * Called when the view needs to be shown. 108 */ 109 abstract public void show(); 110 111 /** 112 * Called when a key has woken the device to give us a chance to adjust our 113 * state according the the key. We are responsible for waking the device 114 * (by poking the wake lock) once we are ready. 115 * 116 * The 'Tq' suffix is per the documentation in {@link android.view.WindowManagerPolicy}. 117 * Be sure not to take any action that takes a long time; any significant 118 * action should be posted to a handler. 119 * 120 * @param keyCode The wake key, which may be relevant for configuring the 121 * keyguard. May be {@link KeyEvent#KEYCODE_UNKNOWN} if waking for a reason 122 * other than a key press. 123 */ 124 abstract public void wakeWhenReadyTq(int keyCode); 125 126 /** 127 * Verify that the user can get past the keyguard securely. This is called, 128 * for example, when the phone disables the keyguard but then wants to launch 129 * something else that requires secure access. 130 * 131 * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)} 132 */ 133 abstract public void verifyUnlock(); 134 135 /** 136 * Called before this view is being removed. 137 */ 138 abstract public void cleanUp(); 139 140 @Override 141 public boolean dispatchKeyEvent(KeyEvent event) { 142 if (interceptMediaKey(event)) { 143 return true; 144 } 145 return super.dispatchKeyEvent(event); 146 } 147 148 /** 149 * Allows the media keys to work when the keyguard is showing. 150 * The media keys should be of no interest to the actual keyguard view(s), 151 * so intercepting them here should not be of any harm. 152 * @param event The key event 153 * @return whether the event was consumed as a media key. 154 */ 155 private boolean interceptMediaKey(KeyEvent event) { 156 final int keyCode = event.getKeyCode(); 157 if (event.getAction() == KeyEvent.ACTION_DOWN) { 158 switch (keyCode) { 159 case KeyEvent.KEYCODE_MEDIA_PLAY: 160 case KeyEvent.KEYCODE_MEDIA_PAUSE: 161 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 162 /* Suppress PLAY/PAUSE toggle when phone is ringing or 163 * in-call to avoid music playback */ 164 if (mTelephonyManager == null) { 165 mTelephonyManager = (TelephonyManager) getContext().getSystemService( 166 Context.TELEPHONY_SERVICE); 167 } 168 if (mTelephonyManager != null && 169 mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { 170 return true; // suppress key event 171 } 172 case KeyEvent.KEYCODE_MUTE: 173 case KeyEvent.KEYCODE_HEADSETHOOK: 174 case KeyEvent.KEYCODE_MEDIA_STOP: 175 case KeyEvent.KEYCODE_MEDIA_NEXT: 176 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 177 case KeyEvent.KEYCODE_MEDIA_REWIND: 178 case KeyEvent.KEYCODE_MEDIA_RECORD: 179 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { 180 handleMediaKeyEvent(event); 181 return true; 182 } 183 184 case KeyEvent.KEYCODE_VOLUME_UP: 185 case KeyEvent.KEYCODE_VOLUME_DOWN: 186 case KeyEvent.KEYCODE_VOLUME_MUTE: { 187 if (KEYGUARD_MANAGES_VOLUME) { 188 synchronized (this) { 189 if (mAudioManager == null) { 190 mAudioManager = (AudioManager) getContext().getSystemService( 191 Context.AUDIO_SERVICE); 192 } 193 } 194 // Volume buttons should only function for music (local or remote). 195 // TODO: Actually handle MUTE. 196 mAudioManager.adjustLocalOrRemoteStreamVolume( 197 AudioManager.STREAM_MUSIC, 198 keyCode == KeyEvent.KEYCODE_VOLUME_UP 199 ? AudioManager.ADJUST_RAISE 200 : AudioManager.ADJUST_LOWER); 201 // Don't execute default volume behavior 202 return true; 203 } else { 204 return false; 205 } 206 } 207 } 208 } else if (event.getAction() == KeyEvent.ACTION_UP) { 209 switch (keyCode) { 210 case KeyEvent.KEYCODE_MUTE: 211 case KeyEvent.KEYCODE_HEADSETHOOK: 212 case KeyEvent.KEYCODE_MEDIA_PLAY: 213 case KeyEvent.KEYCODE_MEDIA_PAUSE: 214 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 215 case KeyEvent.KEYCODE_MEDIA_STOP: 216 case KeyEvent.KEYCODE_MEDIA_NEXT: 217 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 218 case KeyEvent.KEYCODE_MEDIA_REWIND: 219 case KeyEvent.KEYCODE_MEDIA_RECORD: 220 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { 221 handleMediaKeyEvent(event); 222 return true; 223 } 224 } 225 } 226 return false; 227 } 228 229 void handleMediaKeyEvent(KeyEvent keyEvent) { 230 IAudioService audioService = IAudioService.Stub.asInterface( 231 ServiceManager.checkService(Context.AUDIO_SERVICE)); 232 if (audioService != null) { 233 try { 234 audioService.dispatchMediaKeyEvent(keyEvent); 235 } catch (RemoteException e) { 236 Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e); 237 } 238 } else { 239 Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event"); 240 } 241 } 242 243 @Override 244 public void dispatchSystemUiVisibilityChanged(int visibility) { 245 super.dispatchSystemUiVisibilityChanged(visibility); 246 setSystemUiVisibility(STATUS_BAR_DISABLE_BACK); 247 } 248 249 public void setViewMediatorCallback( 250 KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) { 251 mViewMediatorCallback = viewMediatorCallback; 252 } 253 254} 255