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