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