1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.car.builtin.keyguard; 18 19 import static android.os.PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON; 20 import static android.os.PowerManager.WAKE_REASON_POWER_BUTTON; 21 22 import android.annotation.NonNull; 23 import android.annotation.SystemApi; 24 import android.car.builtin.util.Slogf; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.ServiceConnection; 29 import android.content.res.Resources; 30 import android.os.Handler; 31 import android.os.IBinder; 32 import android.os.PowerManager; 33 import android.os.RemoteException; 34 import android.os.UserHandle; 35 import android.util.Log; 36 37 import com.android.internal.annotations.GuardedBy; 38 import com.android.internal.policy.IKeyguardDrawnCallback; 39 import com.android.internal.policy.IKeyguardService; 40 import com.android.internal.util.Preconditions; 41 42 import java.io.PrintWriter; 43 import java.util.Arrays; 44 45 /** 46 * Wrapper for KeyguardService 47 * 48 * Simplified version of com.android.server.policy.keyguard.KeyguardServiceDelegate. If something 49 * is not working, check for oversimplification from that class. 50 * 51 * @hide 52 */ 53 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 54 public final class KeyguardServiceDelegate { 55 private static final String TAG = KeyguardServiceDelegate.class.getSimpleName(); 56 private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG); 57 58 private final KeyguardStateMonitor.StateCallback mStateCallback; 59 private final Object mLock = new Object(); 60 private IKeyguardService mKeyguardService; 61 private KeyguardStateMonitor mKeyguardStateMonitor; 62 @GuardedBy("mLock") 63 private KeyguardLockedStateCallback mLockedStateCallback; 64 private Handler mHandler; 65 private int mUserId; 66 private int[] mDisplays; 67 68 private final IKeyguardDrawnCallback.Stub mKeyguardShowDelegate = 69 new IKeyguardDrawnCallback.Stub() { 70 @Override 71 public void onDrawn() { 72 if (DBG) { 73 Slogf.v(TAG, "KeyguardShowDelegate.onDrawn userId=%d", mUserId); 74 } 75 } 76 }; 77 78 private final ServiceConnection mKeyguardConnection = new ServiceConnection() { 79 @Override 80 public void onServiceConnected(ComponentName name, IBinder service) { 81 if (DBG) { 82 Slogf.d(TAG, "Keyguard connected for user %d", mUserId); 83 } 84 try { 85 // replicated PhoneWindowManager order 86 mKeyguardService = IKeyguardService.Stub.asInterface(service); 87 mKeyguardService.onSystemReady(); 88 mKeyguardService.setCurrentUser(mUserId); 89 mKeyguardStateMonitor = new KeyguardStateMonitor(mKeyguardService, mUserId, 90 mStateCallback); 91 92 mKeyguardService.setSwitchingUser(false); 93 mKeyguardService.onBootCompleted(); 94 mKeyguardService.onStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN, false); 95 mKeyguardService.onFinishedWakingUp(); 96 mKeyguardService.onScreenTurningOn(mKeyguardShowDelegate); 97 mKeyguardService.onScreenTurnedOn(); 98 } catch (Exception e) { 99 Slogf.e(TAG, e, "Can not start the keyguard"); 100 } 101 } 102 103 @Override 104 public void onServiceDisconnected(ComponentName name) { 105 if (DBG) { 106 Slogf.d(TAG, "Keyguard disconnected for user %d", mUserId); 107 } 108 mKeyguardService = null; 109 mKeyguardStateMonitor = null; 110 // TODO(b/258238612): Enable once ActivityTaskManagerService APIs are ready 111 // mHandler.post(() -> { 112 // try { 113 // ActivityTaskManager.getService().setLockScreenShownForDisplays( 114 // /* showingKeyguard= */ true, /* showingAod= */ false, mDisplays); 115 // } catch (RemoteException e) { 116 // } 117 // }); 118 } 119 }; 120 KeyguardServiceDelegate()121 public KeyguardServiceDelegate() { 122 mStateCallback = showing -> { 123 if (mHandler != null) { 124 mHandler.post(() -> { 125 synchronized (mLock) { 126 if (mLockedStateCallback != null) { 127 mLockedStateCallback.onKeyguardLockedStateChanged(showing); 128 } 129 } 130 }); 131 } 132 }; 133 } 134 135 /** 136 * Binds to the KeyguardService for a particular user and display(s). 137 */ bindService(Context context, UserHandle userHandle, int[] displays)138 public void bindService(Context context, UserHandle userHandle, int[] displays) { 139 if (DBG) { 140 Slogf.v(TAG, "bindService for user=%d, displays=%s", userHandle.getIdentifier(), 141 Arrays.toString(displays)); 142 } 143 mHandler = new Handler(context.getMainLooper()); 144 mUserId = userHandle.getIdentifier(); 145 mDisplays = displays; 146 147 Intent intent = new Intent(); 148 Resources resources = context.getApplicationContext().getResources(); 149 150 ComponentName keyguardComponent = ComponentName.unflattenFromString( 151 resources.getString(com.android.internal.R.string.config_keyguardComponent)); 152 intent.setComponent(keyguardComponent); 153 154 if (!context.bindServiceAsUser(intent, mKeyguardConnection, 155 Context.BIND_AUTO_CREATE, mHandler, userHandle)) { 156 Slogf.e(TAG, "Keyguard: can't bind to " + keyguardComponent); 157 } else { 158 if (DBG) { 159 Slogf.v(TAG, "Keyguard started for user=%d", mUserId); 160 } 161 } 162 } 163 164 /** 165 * Unbinds the currently bound KeyguardService. 166 */ stop(Context context)167 public void stop(Context context) { 168 try { 169 context.unbindService(mKeyguardConnection); 170 } catch (Exception e) { 171 Slogf.e(TAG, "Can't unbind the KeyguardService", e); 172 } 173 } 174 175 /** 176 * Returns whether Keyguard is showing for this delegate. If Keyguard is not bound, return true 177 * to assume the most secure state. 178 */ isShowing()179 public boolean isShowing() { 180 if (mKeyguardStateMonitor == null) { 181 if (DBG) { 182 Slogf.d(TAG, "mKeyguardStateMonitor null for user=%d - returning default", mUserId); 183 } 184 return true; 185 } 186 boolean showing = mKeyguardStateMonitor.isShowing(); 187 if (DBG) { 188 Slogf.d(TAG, "isShowing=%b for user=%d", showing, mUserId); 189 } 190 return showing; 191 } 192 193 /** 194 * Register a KeyguardLockedStateCallback for this delegate. 195 */ registerKeyguardLockedStateCallback( @onNull KeyguardLockedStateCallback callback)196 public void registerKeyguardLockedStateCallback( 197 @NonNull KeyguardLockedStateCallback callback) { 198 synchronized (mLock) { 199 Preconditions.checkState(mLockedStateCallback == null, 200 "Keyguard locked state callback already registered"); 201 mLockedStateCallback = callback; 202 } 203 } 204 205 /** 206 * Unregister a KeyguardLockedStateCallback from this delegate. 207 */ unregisterKeyguardLockedStateCallback()208 public void unregisterKeyguardLockedStateCallback() { 209 synchronized (mLock) { 210 Preconditions.checkNotNull(mLockedStateCallback, 211 "Keyguard locked state callback never registered"); 212 mLockedStateCallback = null; 213 } 214 } 215 216 /** 217 * Notify Keyguard of a display on event. 218 */ notifyDisplayOn()219 public void notifyDisplayOn() { 220 if (mKeyguardService == null) { 221 Slogf.w(TAG, "onDisplayOn - null KeyguardService"); 222 return; 223 } 224 try { 225 if (DBG) { 226 Slogf.v(TAG, "onDisplayOn"); 227 } 228 mKeyguardService.onStartedWakingUp( 229 WAKE_REASON_POWER_BUTTON, /* cameraGestureTriggered= */ false); 230 mKeyguardService.onScreenTurningOn(mKeyguardShowDelegate); 231 mKeyguardService.onScreenTurnedOn(); 232 mKeyguardService.onFinishedWakingUp(); 233 } catch (RemoteException e) { 234 Slogf.e(TAG, "RemoteException", e); 235 } 236 } 237 238 /** 239 * Notify Keyguard of a display off event. 240 */ notifyDisplayOff()241 public void notifyDisplayOff() { 242 if (mKeyguardService == null) { 243 Slogf.w(TAG, "onDisplayOff - null KeyguardService"); 244 return; 245 } 246 try { 247 if (DBG) { 248 Slogf.v(TAG, "onDisplayOff"); 249 } 250 // TODO(b/258238612): check that nothing is missed comparing to foreground user behavior 251 mKeyguardService.onStartedGoingToSleep(GO_TO_SLEEP_REASON_POWER_BUTTON); 252 mKeyguardService.onScreenTurningOff(); 253 mKeyguardService.onScreenTurnedOff(); 254 mKeyguardService.onFinishedGoingToSleep(GO_TO_SLEEP_REASON_POWER_BUTTON, false); 255 } catch (RemoteException e) { 256 Slogf.e(TAG, "RemoteException", e); 257 } 258 } 259 260 /** 261 * Dump the KeyguardServiceDelegate state 262 */ dump(PrintWriter writer)263 public void dump(PrintWriter writer) { 264 writer.println("*KeyguardServiceDelegate*"); 265 writer.println("Keyguard service connected = " + (mKeyguardService != null)); 266 if (mKeyguardStateMonitor != null) { 267 mKeyguardStateMonitor.dump(writer); 268 } 269 } 270 271 /** 272 * Callback interface that executes when the keyguard locked state changes. 273 */ 274 public interface KeyguardLockedStateCallback { 275 /** 276 * Callback function that executes when the keyguard locked state changes. 277 */ onKeyguardLockedStateChanged(boolean isKeyguardLocked)278 void onKeyguardLockedStateChanged(boolean isKeyguardLocked); 279 } 280 } 281