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