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.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