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.service.remotelockscreenvalidation;
18 
19 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SdkConstant;
24 import android.annotation.SystemApi;
25 import android.app.RemoteLockscreenValidationResult;
26 import android.app.Service;
27 import android.content.Intent;
28 import android.os.Handler;
29 import android.os.IBinder;
30 import android.os.Looper;
31 import android.os.OutcomeReceiver;
32 import android.os.RemoteException;
33 import android.util.Log;
34 
35 /**
36  * Provides an interface to validate a remote device's lockscreen
37  * @hide
38  */
39 @SystemApi
40 public abstract class RemoteLockscreenValidationService extends Service {
41 
42     /**
43      * The {@link Intent} that must be declared as handled by the service. To be supported, the
44      * service must also require the
45      * {@link android.Manifest.permission#BIND_REMOTE_LOCKSCREEN_VALIDATION_SERVICE}
46      * permission so that other applications can not abuse it.
47      */
48     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
49     public static final String SERVICE_INTERFACE =
50             "android.service.remotelockscreenvalidation.RemoteLockscreenValidationService";
51     private static final String TAG = RemoteLockscreenValidationService.class.getSimpleName();
52 
53     private final Handler mHandler = new Handler(Looper.getMainLooper());
54     private final IRemoteLockscreenValidationService mInterface =
55             new IRemoteLockscreenValidationService.Stub() {
56                 @Override
57                 public void validateLockscreenGuess(
58                         byte[] guess, IRemoteLockscreenValidationCallback callback) {
59                     mHandler.sendMessage(obtainMessage(
60                             RemoteLockscreenValidationService::onValidateLockscreenGuess,
61                             RemoteLockscreenValidationService.this, guess,
62                             new OutcomeReceiver<RemoteLockscreenValidationResult,
63                                     Exception>() {
64                                 @Override
65                                 public void onResult(RemoteLockscreenValidationResult result) {
66                                     try {
67                                         callback.onSuccess(result);
68                                     } catch (RemoteException e) {
69                                         e.rethrowFromSystemServer();
70                                     }
71                                 }
72                                 @Override
73                                 public void onError(Exception e) {
74                                     try {
75                                         callback.onFailure(e.getMessage());
76                                     } catch (RemoteException ex) {
77                                         ex.rethrowFromSystemServer();
78                                     }
79                                 }
80                             }
81                     ));
82                 }
83             };
84 
85     @Override
86     @Nullable
onBind(@onNull Intent intent)87     public final IBinder onBind(@NonNull Intent intent) {
88         if (!SERVICE_INTERFACE.equals(intent.getAction())) {
89             Log.w(TAG, "Wrong action");
90             return null;
91         }
92         return mInterface.asBinder();
93     }
94 
95     /**
96      * Validates the lockscreen guess.
97      *
98      * <p>Implementation should send guess to remote device and perform lockscreen validation
99      * using {@link android.app.KeyguardManager#validateRemoteLockScreen}.
100      *
101      * @param guess lockscreen guess
102      * @param callback object used to relay the response of the guess validation
103      */
onValidateLockscreenGuess(@onNull byte[] guess, @NonNull OutcomeReceiver<RemoteLockscreenValidationResult, Exception> callback)104     public abstract void onValidateLockscreenGuess(@NonNull byte[] guess,
105             @NonNull OutcomeReceiver<RemoteLockscreenValidationResult, Exception> callback);
106 }
107