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