Home | History | Annotate | Download | only in keyguard
      1 package com.android.server.policy.keyguard;
      2 
      3 import android.app.ActivityManager;
      4 import android.content.ComponentName;
      5 import android.content.Context;
      6 import android.content.Intent;
      7 import android.content.ServiceConnection;
      8 import android.content.res.Resources;
      9 import android.os.Bundle;
     10 import android.os.Handler;
     11 import android.os.IBinder;
     12 import android.os.RemoteException;
     13 import android.os.UserHandle;
     14 import android.util.Log;
     15 import android.util.Slog;
     16 import android.view.WindowManagerPolicy.OnKeyguardExitResult;
     17 
     18 import com.android.internal.policy.IKeyguardDismissCallback;
     19 import com.android.internal.policy.IKeyguardDrawnCallback;
     20 import com.android.internal.policy.IKeyguardExitCallback;
     21 import com.android.internal.policy.IKeyguardService;
     22 import com.android.server.UiThread;
     23 
     24 import java.io.PrintWriter;
     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     private static final String TAG = "KeyguardServiceDelegate";
     33     private static final boolean DEBUG = false;
     34 
     35     private static final int SCREEN_STATE_OFF = 0;
     36     private static final int SCREEN_STATE_TURNING_ON = 1;
     37     private static final int SCREEN_STATE_ON = 2;
     38 
     39     private static final int INTERACTIVE_STATE_SLEEP = 0;
     40     private static final int INTERACTIVE_STATE_AWAKE = 1;
     41     private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 2;
     42 
     43     protected KeyguardServiceWrapper mKeyguardService;
     44     private final Context mContext;
     45     private final Handler mHandler;
     46     private final KeyguardState mKeyguardState = new KeyguardState();
     47     private final KeyguardStateMonitor.StateCallback mCallback;
     48 
     49     private DrawnListener mDrawnListenerWhenConnect;
     50 
     51     private static final class KeyguardState {
     52         KeyguardState() {
     53             reset();
     54         }
     55         boolean showing;
     56         boolean showingAndNotOccluded;
     57         boolean inputRestricted;
     58         boolean occluded;
     59         boolean secure;
     60         boolean dreaming;
     61         boolean systemIsReady;
     62         boolean deviceHasKeyguard;
     63         public boolean enabled;
     64         public int offReason;
     65         public int currentUser;
     66         public boolean bootCompleted;
     67         public int screenState;
     68         public int interactiveState;
     69 
     70         private void reset() {
     71             // Assume keyguard is showing and secure until we know for sure. This is here in
     72             // the event something checks before the service is actually started.
     73             // KeyguardService itself should default to this state until the real state is known.
     74             showing = true;
     75             showingAndNotOccluded = true;
     76             secure = true;
     77             deviceHasKeyguard = true;
     78             enabled = true;
     79             currentUser = UserHandle.USER_NULL;
     80         }
     81     };
     82 
     83     public interface DrawnListener {
     84         void onDrawn();
     85     }
     86 
     87     // A delegate class to map a particular invocation with a ShowListener object.
     88     private final class KeyguardShowDelegate extends IKeyguardDrawnCallback.Stub {
     89         private DrawnListener mDrawnListener;
     90 
     91         KeyguardShowDelegate(DrawnListener drawnListener) {
     92             mDrawnListener = drawnListener;
     93         }
     94 
     95         @Override
     96         public void onDrawn() throws RemoteException {
     97             if (DEBUG) Log.v(TAG, "**** SHOWN CALLED ****");
     98             if (mDrawnListener != null) {
     99                 mDrawnListener.onDrawn();
    100             }
    101         }
    102     };
    103 
    104     // A delegate class to map a particular invocation with an OnKeyguardExitResult object.
    105     private final class KeyguardExitDelegate extends IKeyguardExitCallback.Stub {
    106         private OnKeyguardExitResult mOnKeyguardExitResult;
    107 
    108         KeyguardExitDelegate(OnKeyguardExitResult onKeyguardExitResult) {
    109             mOnKeyguardExitResult = onKeyguardExitResult;
    110         }
    111 
    112         @Override
    113         public void onKeyguardExitResult(boolean success) throws RemoteException {
    114             if (DEBUG) Log.v(TAG, "**** onKeyguardExitResult(" + success +") CALLED ****");
    115             if (mOnKeyguardExitResult != null) {
    116                 mOnKeyguardExitResult.onKeyguardExitResult(success);
    117             }
    118         }
    119     };
    120 
    121     public KeyguardServiceDelegate(Context context, KeyguardStateMonitor.StateCallback callback) {
    122         mContext = context;
    123         mHandler = UiThread.getHandler();
    124         mCallback = callback;
    125     }
    126 
    127     public void bindService(Context context) {
    128         Intent intent = new Intent();
    129         final Resources resources = context.getApplicationContext().getResources();
    130 
    131         final ComponentName keyguardComponent = ComponentName.unflattenFromString(
    132                 resources.getString(com.android.internal.R.string.config_keyguardComponent));
    133         intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    134         intent.setComponent(keyguardComponent);
    135 
    136         if (!context.bindServiceAsUser(intent, mKeyguardConnection,
    137                 Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {
    138             Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
    139             mKeyguardState.showing = false;
    140             mKeyguardState.showingAndNotOccluded = false;
    141             mKeyguardState.secure = false;
    142             synchronized (mKeyguardState) {
    143                 // TODO: Fix synchronisation model in this class. The other state in this class
    144                 // is at least self-healing but a race condition here can lead to the scrim being
    145                 // stuck on keyguard-less devices.
    146                 mKeyguardState.deviceHasKeyguard = false;
    147             }
    148         } else {
    149             if (DEBUG) Log.v(TAG, "*** Keyguard started");
    150         }
    151     }
    152 
    153     private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
    154         @Override
    155         public void onServiceConnected(ComponentName name, IBinder service) {
    156             if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
    157             mKeyguardService = new KeyguardServiceWrapper(mContext,
    158                     IKeyguardService.Stub.asInterface(service), mCallback);
    159             if (mKeyguardState.systemIsReady) {
    160                 // If the system is ready, it means keyguard crashed and restarted.
    161                 mKeyguardService.onSystemReady();
    162                 if (mKeyguardState.currentUser != UserHandle.USER_NULL) {
    163                     // There has been a user switch earlier
    164                     mKeyguardService.setCurrentUser(mKeyguardState.currentUser);
    165                 }
    166                 // This is used to hide the scrim once keyguard displays.
    167                 if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
    168                     mKeyguardService.onStartedWakingUp();
    169                 }
    170                 if (mKeyguardState.screenState == SCREEN_STATE_ON
    171                         || mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) {
    172                     mKeyguardService.onScreenTurningOn(
    173                             new KeyguardShowDelegate(mDrawnListenerWhenConnect));
    174                 }
    175                 if (mKeyguardState.screenState == SCREEN_STATE_ON) {
    176                     mKeyguardService.onScreenTurnedOn();
    177                 }
    178                 mDrawnListenerWhenConnect = null;
    179             }
    180             if (mKeyguardState.bootCompleted) {
    181                 mKeyguardService.onBootCompleted();
    182             }
    183             if (mKeyguardState.occluded) {
    184                 mKeyguardService.setOccluded(mKeyguardState.occluded, false /* animate */);
    185             }
    186             if (!mKeyguardState.enabled) {
    187                 mKeyguardService.setKeyguardEnabled(mKeyguardState.enabled);
    188             }
    189         }
    190 
    191         @Override
    192         public void onServiceDisconnected(ComponentName name) {
    193             if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
    194             mKeyguardService = null;
    195             mKeyguardState.reset();
    196             mHandler.post(() -> {
    197                 try {
    198                     ActivityManager.getService().setLockScreenShown(true);
    199                 } catch (RemoteException e) {
    200                     // Local call.
    201                 }
    202             });
    203         }
    204     };
    205 
    206     public boolean isShowing() {
    207         if (mKeyguardService != null) {
    208             mKeyguardState.showing = mKeyguardService.isShowing();
    209         }
    210         return mKeyguardState.showing;
    211     }
    212 
    213     public boolean isTrusted() {
    214         if (mKeyguardService != null) {
    215             return mKeyguardService.isTrusted();
    216         }
    217         return false;
    218     }
    219 
    220     public boolean hasLockscreenWallpaper() {
    221         if (mKeyguardService != null) {
    222             return mKeyguardService.hasLockscreenWallpaper();
    223         }
    224         return false;
    225     }
    226 
    227     public boolean isInputRestricted() {
    228         if (mKeyguardService != null) {
    229             mKeyguardState.inputRestricted = mKeyguardService.isInputRestricted();
    230         }
    231         return mKeyguardState.inputRestricted;
    232     }
    233 
    234     public void verifyUnlock(final OnKeyguardExitResult onKeyguardExitResult) {
    235         if (mKeyguardService != null) {
    236             mKeyguardService.verifyUnlock(new KeyguardExitDelegate(onKeyguardExitResult));
    237         }
    238     }
    239 
    240     public void setOccluded(boolean isOccluded, boolean animate) {
    241         if (mKeyguardService != null) {
    242             if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ") animate=" + animate);
    243             mKeyguardService.setOccluded(isOccluded, animate);
    244         }
    245         mKeyguardState.occluded = isOccluded;
    246     }
    247 
    248     public void dismiss(IKeyguardDismissCallback callback) {
    249         if (mKeyguardService != null) {
    250             mKeyguardService.dismiss(callback);
    251         }
    252     }
    253 
    254     public boolean isSecure(int userId) {
    255         if (mKeyguardService != null) {
    256             mKeyguardState.secure = mKeyguardService.isSecure(userId);
    257         }
    258         return mKeyguardState.secure;
    259     }
    260 
    261     public void onDreamingStarted() {
    262         if (mKeyguardService != null) {
    263             mKeyguardService.onDreamingStarted();
    264         }
    265         mKeyguardState.dreaming = true;
    266     }
    267 
    268     public void onDreamingStopped() {
    269         if (mKeyguardService != null) {
    270             mKeyguardService.onDreamingStopped();
    271         }
    272         mKeyguardState.dreaming = false;
    273     }
    274 
    275     public void onStartedWakingUp() {
    276         if (mKeyguardService != null) {
    277             if (DEBUG) Log.v(TAG, "onStartedWakingUp()");
    278             mKeyguardService.onStartedWakingUp();
    279         }
    280         mKeyguardState.interactiveState = INTERACTIVE_STATE_AWAKE;
    281     }
    282 
    283     public void onScreenTurnedOff() {
    284         if (mKeyguardService != null) {
    285             if (DEBUG) Log.v(TAG, "onScreenTurnedOff()");
    286             mKeyguardService.onScreenTurnedOff();
    287         }
    288         mKeyguardState.screenState = SCREEN_STATE_OFF;
    289     }
    290 
    291     public void onScreenTurningOn(final DrawnListener drawnListener) {
    292         if (mKeyguardService != null) {
    293             if (DEBUG) Log.v(TAG, "onScreenTurnedOn(showListener = " + drawnListener + ")");
    294             mKeyguardService.onScreenTurningOn(new KeyguardShowDelegate(drawnListener));
    295         } else {
    296             // try again when we establish a connection
    297             Slog.w(TAG, "onScreenTurningOn(): no keyguard service!");
    298             // This shouldn't happen, but if it does, show the scrim immediately and
    299             // invoke the listener's callback after the service actually connects.
    300             mDrawnListenerWhenConnect = drawnListener;
    301         }
    302         mKeyguardState.screenState = SCREEN_STATE_TURNING_ON;
    303     }
    304 
    305     public void onScreenTurnedOn() {
    306         if (mKeyguardService != null) {
    307             if (DEBUG) Log.v(TAG, "onScreenTurnedOn()");
    308             mKeyguardService.onScreenTurnedOn();
    309         }
    310         mKeyguardState.screenState = SCREEN_STATE_ON;
    311     }
    312 
    313     public void onStartedGoingToSleep(int why) {
    314         if (mKeyguardService != null) {
    315             mKeyguardService.onStartedGoingToSleep(why);
    316         }
    317         mKeyguardState.offReason = why;
    318         mKeyguardState.interactiveState = INTERACTIVE_STATE_GOING_TO_SLEEP;
    319     }
    320 
    321     public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {
    322         if (mKeyguardService != null) {
    323             mKeyguardService.onFinishedGoingToSleep(why, cameraGestureTriggered);
    324         }
    325         mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP;
    326     }
    327 
    328     public void setKeyguardEnabled(boolean enabled) {
    329         if (mKeyguardService != null) {
    330             mKeyguardService.setKeyguardEnabled(enabled);
    331         }
    332         mKeyguardState.enabled = enabled;
    333     }
    334 
    335     public void onSystemReady() {
    336         if (mKeyguardService != null) {
    337             mKeyguardService.onSystemReady();
    338         } else {
    339             mKeyguardState.systemIsReady = true;
    340         }
    341     }
    342 
    343     public void doKeyguardTimeout(Bundle options) {
    344         if (mKeyguardService != null) {
    345             mKeyguardService.doKeyguardTimeout(options);
    346         }
    347     }
    348 
    349     public void setCurrentUser(int newUserId) {
    350         if (mKeyguardService != null) {
    351             mKeyguardService.setCurrentUser(newUserId);
    352         }
    353         mKeyguardState.currentUser = newUserId;
    354     }
    355 
    356     public void setSwitchingUser(boolean switching) {
    357         if (mKeyguardService != null) {
    358             mKeyguardService.setSwitchingUser(switching);
    359         }
    360     }
    361 
    362     public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
    363         if (mKeyguardService != null) {
    364             mKeyguardService.startKeyguardExitAnimation(startTime, fadeoutDuration);
    365         }
    366     }
    367 
    368     public void onBootCompleted() {
    369         if (mKeyguardService != null) {
    370             mKeyguardService.onBootCompleted();
    371         }
    372         mKeyguardState.bootCompleted = true;
    373     }
    374 
    375     public void onShortPowerPressedGoHome() {
    376         if (mKeyguardService != null) {
    377             mKeyguardService.onShortPowerPressedGoHome();
    378         }
    379     }
    380 
    381     public void dump(String prefix, PrintWriter pw) {
    382         pw.println(prefix + TAG);
    383         prefix += "  ";
    384         pw.println(prefix + "showing=" + mKeyguardState.showing);
    385         pw.println(prefix + "showingAndNotOccluded=" + mKeyguardState.showingAndNotOccluded);
    386         pw.println(prefix + "inputRestricted=" + mKeyguardState.inputRestricted);
    387         pw.println(prefix + "occluded=" + mKeyguardState.occluded);
    388         pw.println(prefix + "secure=" + mKeyguardState.secure);
    389         pw.println(prefix + "dreaming=" + mKeyguardState.dreaming);
    390         pw.println(prefix + "systemIsReady=" + mKeyguardState.systemIsReady);
    391         pw.println(prefix + "deviceHasKeyguard=" + mKeyguardState.deviceHasKeyguard);
    392         pw.println(prefix + "enabled=" + mKeyguardState.enabled);
    393         pw.println(prefix + "offReason=" + mKeyguardState.offReason);
    394         pw.println(prefix + "currentUser=" + mKeyguardState.currentUser);
    395         pw.println(prefix + "bootCompleted=" + mKeyguardState.bootCompleted);
    396         pw.println(prefix + "screenState=" + mKeyguardState.screenState);
    397         pw.println(prefix + "interactiveState=" + mKeyguardState.interactiveState);
    398         if (mKeyguardService != null) {
    399             mKeyguardService.dump(prefix, pw);
    400         }
    401     }
    402 }
    403