1 package com.android.internal.policy.impl.keyguard; 2 3 import android.content.ComponentName; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.content.ServiceConnection; 7 import android.content.pm.ActivityInfo; 8 import android.graphics.PixelFormat; 9 import android.os.Bundle; 10 import android.os.IBinder; 11 import android.os.RemoteException; 12 import android.os.UserHandle; 13 import android.util.Log; 14 import android.util.Slog; 15 import android.view.KeyEvent; 16 import android.view.View; 17 import android.view.ViewGroup; 18 import android.view.WindowManager; 19 import android.view.WindowManagerPolicy.OnKeyguardExitResult; 20 21 import com.android.internal.policy.IKeyguardExitCallback; 22 import com.android.internal.policy.IKeyguardShowCallback; 23 import com.android.internal.policy.IKeyguardService; 24 import com.android.internal.widget.LockPatternUtils; 25 26 /** 27 * A local class that keeps a cache of keyguard state that can be restored in the event 28 * keyguard crashes. It currently also allows runtime-selectable 29 * local or remote instances of keyguard. 30 */ 31 public class KeyguardServiceDelegate { 32 // TODO: propagate changes to these to {@link KeyguardTouchDelegate} 33 public static final String KEYGUARD_PACKAGE = "com.android.keyguard"; 34 public static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService"; 35 36 private static final String TAG = "KeyguardServiceDelegate"; 37 private static final boolean DEBUG = true; 38 protected KeyguardServiceWrapper mKeyguardService; 39 private View mScrim; // shown if keyguard crashes 40 private KeyguardState mKeyguardState = new KeyguardState(); 41 42 /* package */ static final class KeyguardState { 43 KeyguardState() { 44 // Assume keyguard is showing and secure until we know for sure. This is here in 45 // the event something checks before the service is actually started. 46 // KeyguardService itself should default to this state until the real state is known. 47 showing = true; 48 showingAndNotHidden = true; 49 secure = true; 50 } 51 boolean showing; 52 boolean showingAndNotHidden; 53 boolean inputRestricted; 54 boolean hidden; 55 boolean secure; 56 boolean dreaming; 57 boolean systemIsReady; 58 public boolean enabled; 59 public boolean dismissable; 60 public int offReason; 61 public int currentUser; 62 public boolean screenIsOn; 63 public boolean bootCompleted; 64 }; 65 66 public interface ShowListener { 67 public void onShown(IBinder windowToken); 68 } 69 70 // A delegate class to map a particular invocation with a ShowListener object. 71 private final class KeyguardShowDelegate extends IKeyguardShowCallback.Stub { 72 private ShowListener mShowListener; 73 74 KeyguardShowDelegate(ShowListener showListener) { 75 mShowListener = showListener; 76 } 77 78 @Override 79 public void onShown(IBinder windowToken) throws RemoteException { 80 if (DEBUG) Log.v(TAG, "**** SHOWN CALLED ****"); 81 if (mShowListener != null) { 82 mShowListener.onShown(windowToken); 83 } 84 hideScrim(); 85 } 86 }; 87 88 // A delegate class to map a particular invocation with an OnKeyguardExitResult object. 89 private final class KeyguardExitDelegate extends IKeyguardExitCallback.Stub { 90 private OnKeyguardExitResult mOnKeyguardExitResult; 91 92 KeyguardExitDelegate(OnKeyguardExitResult onKeyguardExitResult) { 93 mOnKeyguardExitResult = onKeyguardExitResult; 94 } 95 96 @Override 97 public void onKeyguardExitResult(boolean success) throws RemoteException { 98 if (DEBUG) Log.v(TAG, "**** onKeyguardExitResult(" + success +") CALLED ****"); 99 if (mOnKeyguardExitResult != null) { 100 mOnKeyguardExitResult.onKeyguardExitResult(success); 101 } 102 } 103 }; 104 105 public KeyguardServiceDelegate(Context context, LockPatternUtils lockPatternUtils) { 106 Intent intent = new Intent(); 107 intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS); 108 mScrim = createScrim(context); 109 if (!context.bindServiceAsUser(intent, mKeyguardConnection, 110 Context.BIND_AUTO_CREATE, UserHandle.OWNER)) { 111 if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS); 112 } else { 113 if (DEBUG) Log.v(TAG, "*** Keyguard started"); 114 } 115 } 116 117 private final ServiceConnection mKeyguardConnection = new ServiceConnection() { 118 @Override 119 public void onServiceConnected(ComponentName name, IBinder service) { 120 if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)"); 121 mKeyguardService = new KeyguardServiceWrapper( 122 IKeyguardService.Stub.asInterface(service)); 123 if (mKeyguardState.systemIsReady) { 124 // If the system is ready, it means keyguard crashed and restarted. 125 mKeyguardService.onSystemReady(); 126 // This is used to hide the scrim once keyguard displays. 127 mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null)); 128 } 129 if (mKeyguardState.bootCompleted) { 130 mKeyguardService.onBootCompleted(); 131 } 132 } 133 134 @Override 135 public void onServiceDisconnected(ComponentName name) { 136 if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)"); 137 mKeyguardService = null; 138 } 139 140 }; 141 142 public boolean isShowing() { 143 if (mKeyguardService != null) { 144 mKeyguardState.showing = mKeyguardService.isShowing(); 145 } 146 return mKeyguardState.showing; 147 } 148 149 public boolean isShowingAndNotHidden() { 150 if (mKeyguardService != null) { 151 mKeyguardState.showingAndNotHidden = mKeyguardService.isShowingAndNotHidden(); 152 } 153 return mKeyguardState.showingAndNotHidden; 154 } 155 156 public boolean isInputRestricted() { 157 if (mKeyguardService != null) { 158 mKeyguardState.inputRestricted = mKeyguardService.isInputRestricted(); 159 } 160 return mKeyguardState.inputRestricted; 161 } 162 163 public void verifyUnlock(final OnKeyguardExitResult onKeyguardExitResult) { 164 if (mKeyguardService != null) { 165 mKeyguardService.verifyUnlock(new KeyguardExitDelegate(onKeyguardExitResult)); 166 } 167 } 168 169 public void keyguardDone(boolean authenticated, boolean wakeup) { 170 if (mKeyguardService != null) { 171 mKeyguardService.keyguardDone(authenticated, wakeup); 172 } 173 } 174 175 public void setHidden(boolean isHidden) { 176 if (mKeyguardService != null) { 177 mKeyguardService.setHidden(isHidden); 178 } 179 mKeyguardState.hidden = isHidden; 180 } 181 182 public void dismiss() { 183 if (mKeyguardService != null) { 184 mKeyguardService.dismiss(); 185 } 186 } 187 188 public boolean isSecure() { 189 if (mKeyguardService != null) { 190 mKeyguardState.secure = mKeyguardService.isSecure(); 191 } 192 return mKeyguardState.secure; 193 } 194 195 public void onDreamingStarted() { 196 if (mKeyguardService != null) { 197 mKeyguardService.onDreamingStarted(); 198 } 199 mKeyguardState.dreaming = true; 200 } 201 202 public void onDreamingStopped() { 203 if (mKeyguardService != null) { 204 mKeyguardService.onDreamingStopped(); 205 } 206 mKeyguardState.dreaming = false; 207 } 208 209 public void onScreenTurnedOn(final ShowListener showListener) { 210 if (mKeyguardService != null) { 211 if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + showListener + ")"); 212 mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(showListener)); 213 } else { 214 // try again when we establish a connection 215 Slog.w(TAG, "onScreenTurnedOn(): no keyguard service!"); 216 // This shouldn't happen, but if it does, invoke the listener immediately 217 // to avoid a dark screen... 218 showListener.onShown(null); 219 } 220 mKeyguardState.screenIsOn = true; 221 } 222 223 public void onScreenTurnedOff(int why) { 224 if (mKeyguardService != null) { 225 mKeyguardService.onScreenTurnedOff(why); 226 } 227 mKeyguardState.offReason = why; 228 mKeyguardState.screenIsOn = false; 229 } 230 231 public void setKeyguardEnabled(boolean enabled) { 232 if (mKeyguardService != null) { 233 mKeyguardService.setKeyguardEnabled(enabled); 234 } 235 mKeyguardState.enabled = enabled; 236 } 237 238 public boolean isDismissable() { 239 if (mKeyguardService != null) { 240 mKeyguardState.dismissable = mKeyguardService.isDismissable(); 241 } 242 return mKeyguardState.dismissable; 243 } 244 245 public void onSystemReady() { 246 if (mKeyguardService != null) { 247 mKeyguardService.onSystemReady(); 248 } else { 249 if (DEBUG) Log.v(TAG, "onSystemReady() called before keyguard service was ready"); 250 mKeyguardState.systemIsReady = true; 251 } 252 } 253 254 public void doKeyguardTimeout(Bundle options) { 255 if (mKeyguardService != null) { 256 mKeyguardService.doKeyguardTimeout(options); 257 } 258 } 259 260 public void showAssistant() { 261 if (mKeyguardService != null) { 262 mKeyguardService.showAssistant(); 263 } 264 } 265 266 public void setCurrentUser(int newUserId) { 267 if (mKeyguardService != null) { 268 mKeyguardService.setCurrentUser(newUserId); 269 } 270 mKeyguardState.currentUser = newUserId; 271 } 272 273 private static final View createScrim(Context context) { 274 View view = new View(context); 275 276 int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 277 | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR 278 | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN 279 | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER 280 ; 281 282 final int stretch = ViewGroup.LayoutParams.MATCH_PARENT; 283 final int type = WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM; 284 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 285 stretch, stretch, type, flags, PixelFormat.TRANSLUCENT); 286 lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 287 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 288 lp.setTitle("KeyguardScrim"); 289 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 290 wm.addView(view, lp); 291 view.setVisibility(View.GONE); 292 // Disable pretty much everything in statusbar until keyguard comes back and we know 293 // the state of the world. 294 view.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME 295 | View.STATUS_BAR_DISABLE_BACK 296 | View.STATUS_BAR_DISABLE_RECENT 297 | View.STATUS_BAR_DISABLE_EXPAND 298 | View.STATUS_BAR_DISABLE_SEARCH); 299 return view; 300 } 301 302 public void showScrim() { 303 mScrim.post(new Runnable() { 304 @Override 305 public void run() { 306 mScrim.setVisibility(View.VISIBLE); 307 } 308 }); 309 } 310 311 public void hideScrim() { 312 mScrim.post(new Runnable() { 313 @Override 314 public void run() { 315 mScrim.setVisibility(View.GONE); 316 } 317 }); 318 } 319 320 public void onBootCompleted() { 321 if (mKeyguardService != null) { 322 mKeyguardService.onBootCompleted(); 323 } 324 mKeyguardState.bootCompleted = true; 325 } 326 327 } 328