blob: bff1f93fd712c3b6a45ff718cfd89e75c061a7ea [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;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080021import android.media.AudioManager;
Jean-Michel Trivic6802222012-04-30 11:15:03 -070022import android.media.IAudioService;
23import android.os.RemoteException;
24import android.os.ServiceManager;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -080025import android.telephony.TelephonyManager;
Karl Rosaenad297342009-03-24 18:55:19 -070026import android.util.AttributeSet;
Jean-Michel Trivic6802222012-04-30 11:15:03 -070027import android.util.Log;
28import android.util.Slog;
Jim Miller838906b2012-10-19 18:41:25 -070029import android.view.KeyEvent;
30import android.widget.FrameLayout;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080031
32/**
Jim Millerdcb3d842012-08-23 19:18:12 -070033 * Base class for keyguard view. {@link #reset} is where you should
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080034 * reset the state of your view. Use the {@link KeyguardViewCallback} via
35 * {@link #getCallback()} to send information back (such as poking the wake lock,
36 * or finishing the keyguard).
37 *
38 * Handles intercepting of media keys that still work when the keyguard is
39 * showing.
40 */
Jim Miller838906b2012-10-19 18:41:25 -070041public abstract class KeyguardViewBase extends FrameLayout {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080042
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080043 private AudioManager mAudioManager;
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -080044 private TelephonyManager mTelephonyManager = null;
Jim Millerdcb3d842012-08-23 19:18:12 -070045 protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
46
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -080047 // Whether the volume keys should be handled by keyguard. If true, then
48 // they will be handled here for specific media types such as music, otherwise
49 // the audio service will bring up the volume dialog.
Amith Yamasani6243edd2011-12-05 19:58:48 -080050 private static final boolean KEYGUARD_MANAGES_VOLUME = true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080051
Jim Millerdcb3d842012-08-23 19:18:12 -070052 public KeyguardViewBase(Context context) {
53 this(context, null);
54 }
55
56 public KeyguardViewBase(Context context, AttributeSet attrs) {
57 super(context, attrs);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080058 }
59
60 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080061 * Called when the screen turned off.
62 */
63 abstract public void onScreenTurnedOff();
64
65 /**
66 * Called when the screen turned on.
67 */
68 abstract public void onScreenTurnedOn();
69
70 /**
Brian Colonna4284e9d2011-09-28 12:08:58 -040071 * Called when the view needs to be shown.
72 */
73 abstract public void show();
74
75 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080076 * Verify that the user can get past the keyguard securely. This is called,
77 * for example, when the phone disables the keyguard but then wants to launch
78 * something else that requires secure access.
79 *
80 * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
81 */
82 abstract public void verifyUnlock();
83
84 /**
85 * Called before this view is being removed.
86 */
87 abstract public void cleanUp();
88
Jeff Brownc7505bc2012-10-05 21:58:15 -070089 /**
90 * Gets the desired user activity timeout in milliseconds, or -1 if the
91 * default should be used.
92 */
93 abstract public long getUserActivityTimeout();
94
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080095 @Override
96 public boolean dispatchKeyEvent(KeyEvent event) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080097 if (interceptMediaKey(event)) {
98 return true;
99 }
100 return super.dispatchKeyEvent(event);
101 }
102
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800103 /**
Marco Nelissen24d10562009-05-12 14:15:17 -0700104 * Allows the media keys to work when the keyguard is showing.
105 * The media keys should be of no interest to the actual keyguard view(s),
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800106 * so intercepting them here should not be of any harm.
107 * @param event The key event
108 * @return whether the event was consumed as a media key.
109 */
110 private boolean interceptMediaKey(KeyEvent event) {
111 final int keyCode = event.getKeyCode();
112 if (event.getAction() == KeyEvent.ACTION_DOWN) {
113 switch (keyCode) {
Marco Nelissena6face42010-10-25 10:21:59 -0700114 case KeyEvent.KEYCODE_MEDIA_PLAY:
115 case KeyEvent.KEYCODE_MEDIA_PAUSE:
Andy Stadler8b89d692009-04-10 16:24:49 -0700116 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
Jeff Brown4d396052010-10-29 21:50:21 -0700117 /* Suppress PLAY/PAUSE toggle when phone is ringing or
The Android Open Source Projectbc8d29f2009-03-05 20:00:44 -0800118 * in-call to avoid music playback */
119 if (mTelephonyManager == null) {
120 mTelephonyManager = (TelephonyManager) getContext().getSystemService(
121 Context.TELEPHONY_SERVICE);
122 }
123 if (mTelephonyManager != null &&
124 mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
125 return true; // suppress key event
126 }
Jeff Brown4d396052010-10-29 21:50:21 -0700127 case KeyEvent.KEYCODE_MUTE:
128 case KeyEvent.KEYCODE_HEADSETHOOK:
129 case KeyEvent.KEYCODE_MEDIA_STOP:
130 case KeyEvent.KEYCODE_MEDIA_NEXT:
131 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
132 case KeyEvent.KEYCODE_MEDIA_REWIND:
133 case KeyEvent.KEYCODE_MEDIA_RECORD:
Jaekyun Seokbfdad8e2013-07-08 13:53:21 +0900134 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
135 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700136 handleMediaKeyEvent(event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800137 return true;
138 }
139
140 case KeyEvent.KEYCODE_VOLUME_UP:
Jeff Brownb0418da2010-11-01 15:24:01 -0700141 case KeyEvent.KEYCODE_VOLUME_DOWN:
142 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -0800143 if (KEYGUARD_MANAGES_VOLUME) {
144 synchronized (this) {
145 if (mAudioManager == null) {
146 mAudioManager = (AudioManager) getContext().getSystemService(
147 Context.AUDIO_SERVICE);
148 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800149 }
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700150 // Volume buttons should only function for music (local or remote).
151 // TODO: Actually handle MUTE.
152 mAudioManager.adjustLocalOrRemoteStreamVolume(
153 AudioManager.STREAM_MUSIC,
154 keyCode == KeyEvent.KEYCODE_VOLUME_UP
155 ? AudioManager.ADJUST_RAISE
156 : AudioManager.ADJUST_LOWER);
Amith Yamasani2ef6f1b2011-12-01 14:01:30 -0800157 // Don't execute default volume behavior
158 return true;
159 } else {
160 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800161 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800162 }
163 }
164 } else if (event.getAction() == KeyEvent.ACTION_UP) {
165 switch (keyCode) {
166 case KeyEvent.KEYCODE_MUTE:
Jeff Brown4d396052010-10-29 21:50:21 -0700167 case KeyEvent.KEYCODE_HEADSETHOOK:
168 case KeyEvent.KEYCODE_MEDIA_PLAY:
169 case KeyEvent.KEYCODE_MEDIA_PAUSE:
170 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
171 case KeyEvent.KEYCODE_MEDIA_STOP:
172 case KeyEvent.KEYCODE_MEDIA_NEXT:
173 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
174 case KeyEvent.KEYCODE_MEDIA_REWIND:
175 case KeyEvent.KEYCODE_MEDIA_RECORD:
Jaekyun Seokbfdad8e2013-07-08 13:53:21 +0900176 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
177 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700178 handleMediaKeyEvent(event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800179 return true;
180 }
181 }
182 }
183 return false;
184 }
185
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700186 void handleMediaKeyEvent(KeyEvent keyEvent) {
187 IAudioService audioService = IAudioService.Stub.asInterface(
188 ServiceManager.checkService(Context.AUDIO_SERVICE));
189 if (audioService != null) {
190 try {
191 audioService.dispatchMediaKeyEvent(keyEvent);
192 } catch (RemoteException e) {
193 Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e);
194 }
195 } else {
196 Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event");
197 }
198 }
199
Joe Onorato4671ce52011-01-27 21:15:42 -0800200 @Override
201 public void dispatchSystemUiVisibilityChanged(int visibility) {
202 super.dispatchSystemUiVisibilityChanged(visibility);
Jim Millerd6523da2012-10-21 16:47:02 -0700203
204 if (!(mContext instanceof Activity)) {
205 setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
206 }
Joe Onorato4671ce52011-01-27 21:15:42 -0800207 }
Jim Millerdcb3d842012-08-23 19:18:12 -0700208
209 public void setViewMediatorCallback(
210 KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
211 mViewMediatorCallback = viewMediatorCallback;
212 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800213}