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