Home | History | Annotate | Download | only in keyguard
      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