• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2014 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.trust;
18 
19 import android.Manifest;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SdkConstant;
24 import android.annotation.SystemApi;
25 import android.app.Service;
26 import android.app.admin.DevicePolicyManager;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.PackageManager;
31 import android.content.pm.ServiceInfo;
32 import android.os.Bundle;
33 import android.os.Handler;
34 import android.os.IBinder;
35 import android.os.Message;
36 import android.os.PersistableBundle;
37 import android.os.RemoteException;
38 import android.os.UserHandle;
39 import android.os.UserManager;
40 import android.util.Log;
41 import android.util.Slog;
42 
43 import com.android.internal.infra.AndroidFuture;
44 
45 import java.lang.annotation.Retention;
46 import java.lang.annotation.RetentionPolicy;
47 import java.util.List;
48 import java.util.function.Consumer;
49 
50 /**
51  * A service that notifies the system about whether it believes the environment of the device
52  * to be trusted.
53  *
54  * <p>Trust agents may only be provided by the platform. It is expected that there is only
55  * one trust agent installed on the platform. In the event there is more than one,
56  * either trust agent can enable trust.
57  * </p>
58  *
59  * <p>To extend this class, you must declare the service in your manifest file with
60  * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission
61  * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
62  * <pre>
63  * &lt;service android:name=".TrustAgent"
64  *          android:label="&#64;string/service_name"
65  *          android:permission="android.permission.BIND_TRUST_AGENT">
66  *     &lt;intent-filter>
67  *         &lt;action android:name="android.service.trust.TrustAgentService" />
68  *     &lt;/intent-filter>
69  *     &lt;meta-data android:name="android.service.trust.trustagent"
70  *          android:value="&#64;xml/trust_agent" />
71  * &lt;/service></pre>
72  *
73  * <p>The associated meta-data file can specify an activity that is accessible through Settings
74  * and should allow configuring the trust agent, as defined in
75  * {@link android.R.styleable#TrustAgent}. For example:</p>
76  *
77  * <pre>
78  * &lt;trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
79  *          android:settingsActivity=".TrustAgentSettings" /></pre>
80  *
81  * @hide
82  */
83 @SystemApi
84 public class TrustAgentService extends Service {
85 
86     private final String TAG = TrustAgentService.class.getSimpleName() +
87             "[" + getClass().getSimpleName() + "]";
88     private static final boolean DEBUG = false;
89 
90     /**
91      * The {@link Intent} that must be declared as handled by the service.
92      */
93     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
94     public static final String SERVICE_INTERFACE
95             = "android.service.trust.TrustAgentService";
96 
97     /**
98      * The name of the {@code meta-data} tag pointing to additional configuration of the trust
99      * agent.
100      */
101     public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
102 
103 
104     /**
105      * Flag for {@link #grantTrust(CharSequence, long, int)} indicating that trust is being granted
106      * as the direct result of user action - such as solving a security challenge. The hint is used
107      * by the system to optimize the experience. Behavior may vary by device and release, so
108      * one should only set this parameter if it meets the above criteria rather than relying on
109      * the behavior of any particular device or release.
110      */
111     public static final int FLAG_GRANT_TRUST_INITIATED_BY_USER = 1 << 0;
112 
113     /**
114      * Flag for {@link #grantTrust(CharSequence, long, int)} indicating that the agent would like
115      * to dismiss the keyguard. When using this flag, the {@code TrustAgentService} must ensure
116      * it is only set in response to a direct user action with the expectation of dismissing the
117      * keyguard.
118      */
119     public static final int FLAG_GRANT_TRUST_DISMISS_KEYGUARD = 1 << 1;
120 
121     /**
122      * Flag for {@link #grantTrust(CharSequence, long, int)} indicating the platform should
123      * automatically remove trust after some conditions are met (detailed below) with the option for
124      * the agent to renew the trust again later.
125      *
126      * <p>After this is called, the agent will grant trust until the platform thinks an active
127      * user is no longer using that trust. This can happen for any reason as determined by the
128      * platform. For example, if the user dismisses keyguard, the platform will remove trust;
129      * since this does not automatically lock the device, this results in the device locking the
130      * next time the screen turns off.
131      *
132      * <p>When the platform internally removes the agent's trust in this manner, an agent can
133      * re-grant it (via a call to grantTrust) without the user having to unlock the device through
134      * another method (e.g. PIN). This renewable state only persists for a limited time.
135      */
136     public static final int FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE = 1 << 2;
137 
138     /**
139      * Flag for {@link #grantTrust(CharSequence, long, int)} indicating that the message should
140      * be displayed to the user.
141      *
142      * Without this flag, the message passed to {@code grantTrust} is only used for debugging
143      * purposes. With the flag, it may be displayed to the user as the reason why the device is
144      * unlocked. If this flag isn't set OR the message is set to null, the device will display
145      * its own default message for trust granted. If the TrustAgent intentionally doesn't want to
146      * show any message, then it can set this flag AND set the message to an empty string.
147      */
148     public static final int FLAG_GRANT_TRUST_DISPLAY_MESSAGE = 1 << 3;
149 
150     /** @hide */
151     @Retention(RetentionPolicy.SOURCE)
152     @IntDef(flag = true, prefix = { "FLAG_GRANT_TRUST_" }, value = {
153             FLAG_GRANT_TRUST_INITIATED_BY_USER,
154             FLAG_GRANT_TRUST_DISMISS_KEYGUARD,
155             FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE,
156             FLAG_GRANT_TRUST_DISPLAY_MESSAGE,
157     })
158     public @interface GrantTrustFlags {}
159 
160     /**
161      * Int enum indicating that escrow token is active.
162      * See {@link #onEscrowTokenStateReceived(long, int)}
163      *
164      */
165     public static final int TOKEN_STATE_ACTIVE = 1;
166 
167     /**
168      * Int enum indicating that escow token is inactive.
169      * See {@link #onEscrowTokenStateReceived(long, int)}
170      *
171      */
172     public static final int TOKEN_STATE_INACTIVE = 0;
173 
174     /** @hide */
175     @Retention(RetentionPolicy.SOURCE)
176     @IntDef(flag = true, prefix = { "TOKEN_STATE_" }, value = {
177             TOKEN_STATE_ACTIVE,
178             TOKEN_STATE_INACTIVE,
179     })
180     public @interface TokenState {}
181 
182     private static final int MSG_UNLOCK_ATTEMPT = 1;
183     private static final int MSG_CONFIGURE = 2;
184     private static final int MSG_TRUST_TIMEOUT = 3;
185     private static final int MSG_DEVICE_LOCKED = 4;
186     private static final int MSG_DEVICE_UNLOCKED = 5;
187     private static final int MSG_UNLOCK_LOCKOUT = 6;
188     private static final int MSG_ESCROW_TOKEN_ADDED = 7;
189     private static final int MSG_ESCROW_TOKEN_STATE_RECEIVED = 8;
190     private static final int MSG_ESCROW_TOKEN_REMOVED = 9;
191     private static final int MSG_USER_REQUESTED_UNLOCK = 10;
192     private static final int MSG_USER_MAY_REQUEST_UNLOCK = 11;
193 
194     private static final String EXTRA_TOKEN = "token";
195     private static final String EXTRA_TOKEN_HANDLE = "token_handle";
196     private static final String EXTRA_USER_HANDLE = "user_handle";
197     private static final String EXTRA_TOKEN_STATE = "token_state";
198     private static final String EXTRA_TOKEN_REMOVED_RESULT = "token_removed_result";
199     /**
200      * Class containing raw data for a given configuration request.
201      */
202     private static final class ConfigurationData {
203         final IBinder token;
204         final List<PersistableBundle> options;
ConfigurationData(List<PersistableBundle> opts, IBinder t)205         ConfigurationData(List<PersistableBundle> opts, IBinder t) {
206             options = opts;
207             token = t;
208         }
209     }
210 
211     private ITrustAgentServiceCallback mCallback;
212 
213     private Runnable mPendingGrantTrustTask;
214 
215     private boolean mManagingTrust;
216 
217     // Lock used to access mPendingGrantTrustTask and mCallback.
218     private final Object mLock = new Object();
219 
220     private Handler mHandler = new Handler() {
221         public void handleMessage(android.os.Message msg) {
222             switch (msg.what) {
223                 case MSG_UNLOCK_ATTEMPT:
224                     onUnlockAttempt(msg.arg1 != 0);
225                     break;
226                 case MSG_USER_REQUESTED_UNLOCK:
227                     onUserRequestedUnlock(msg.arg1 != 0);
228                     break;
229                 case MSG_USER_MAY_REQUEST_UNLOCK:
230                     onUserMayRequestUnlock();
231                     break;
232                 case MSG_UNLOCK_LOCKOUT:
233                     onDeviceUnlockLockout(msg.arg1);
234                     break;
235                 case MSG_CONFIGURE: {
236                     ConfigurationData data = (ConfigurationData) msg.obj;
237                     boolean result = onConfigure(data.options);
238                     if (data.token != null) {
239                         try {
240                             synchronized (mLock) {
241                                 mCallback.onConfigureCompleted(result, data.token);
242                             }
243                         } catch (RemoteException e) {
244                             onError("calling onSetTrustAgentFeaturesEnabledCompleted()");
245                         }
246                     }
247                     break;
248                 }
249                 case MSG_TRUST_TIMEOUT:
250                     onTrustTimeout();
251                     break;
252                 case MSG_DEVICE_LOCKED:
253                     onDeviceLocked();
254                     break;
255                 case MSG_DEVICE_UNLOCKED:
256                     onDeviceUnlocked();
257                     break;
258                 case MSG_ESCROW_TOKEN_ADDED: {
259                     Bundle data = msg.getData();
260                     byte[] token = data.getByteArray(EXTRA_TOKEN);
261                     long handle = data.getLong(EXTRA_TOKEN_HANDLE);
262                     UserHandle user = (UserHandle) data.getParcelable(EXTRA_USER_HANDLE, android.os.UserHandle.class);
263                     onEscrowTokenAdded(token, handle, user);
264                     break;
265                 }
266                 case MSG_ESCROW_TOKEN_STATE_RECEIVED: {
267                     Bundle data = msg.getData();
268                     long handle = data.getLong(EXTRA_TOKEN_HANDLE);
269                     int tokenState = data.getInt(EXTRA_TOKEN_STATE, TOKEN_STATE_INACTIVE);
270                     onEscrowTokenStateReceived(handle, tokenState);
271                     break;
272                 }
273                 case MSG_ESCROW_TOKEN_REMOVED: {
274                     Bundle data = msg.getData();
275                     long handle = data.getLong(EXTRA_TOKEN_HANDLE);
276                     boolean success = data.getBoolean(EXTRA_TOKEN_REMOVED_RESULT);
277                     onEscrowTokenRemoved(handle, success);
278                     break;
279                 }
280             }
281         }
282     };
283 
284     @Override
onCreate()285     public void onCreate() {
286         super.onCreate();
287         ComponentName component = new ComponentName(this, getClass());
288         try {
289             ServiceInfo serviceInfo = getPackageManager().getServiceInfo(component, 0 /* flags */);
290             if (!Manifest.permission.BIND_TRUST_AGENT.equals(serviceInfo.permission)) {
291                 throw new IllegalStateException(component.flattenToShortString()
292                         + " is not declared with the permission "
293                         + "\"" + Manifest.permission.BIND_TRUST_AGENT + "\"");
294             }
295         } catch (PackageManager.NameNotFoundException e) {
296             Log.e(TAG, "Can't get ServiceInfo for " + component.toShortString());
297         }
298     }
299 
300     /**
301      * Called after the user attempts to authenticate in keyguard with their device credentials,
302      * such as pin, pattern or password.
303      *
304      * @param successful true if the user successfully completed the challenge.
305      */
onUnlockAttempt(boolean successful)306     public void onUnlockAttempt(boolean successful) {
307     }
308 
309     /**
310      * Called when the user has interacted with the locked device such that they are likely to want
311      * it to be unlocked soon. This approximates the timing when, for example, the platform would
312      * check for face authentication to unlock the device.
313      *
314      * This signal can be used for the agent to make preparations to quickly unlock the device
315      * with {@link #onUserRequestedUnlock}. Agents should not unlock the device based solely on this
316      * signal. There is no guarantee that this method will be called before
317      * {@link #onUserRequestedUnlock(boolean)}.
318      */
onUserMayRequestUnlock()319     public void onUserMayRequestUnlock() {
320     }
321 
322     /**
323      * Called when the user has interacted with the locked device such that they likely want it
324      * to be unlocked.
325      *
326      * When this is called, there is a high probability that the user wants to unlock the device and
327      * that a biometric method is either not available or not the optimal method at this time. For
328      * example, this may be called after some kinds of biometric authentication failure.
329      *
330      * A call to this method may be preceded by a call to {@link #onUserMayRequestUnlock} which
331      * the agent can use as a signal to prepare for a subsequent call to this method.
332      *
333      * To attempt to unlock the device, the agent needs to call
334      * {@link #grantTrust(CharSequence, long, int)}.
335      *
336      * @param dismissKeyguard true when the user wants keyguard dismissed
337      *
338      * @see #FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE
339      */
onUserRequestedUnlock(boolean dismissKeyguard)340     public void onUserRequestedUnlock(boolean dismissKeyguard) {
341     }
342 
343     /**
344      * Called when the timeout provided by the agent expires.  Note that this may be called earlier
345      * than requested by the agent if the trust timeout is adjusted by the system or
346      * {@link DevicePolicyManager}.  The agent is expected to re-evaluate the trust state and only
347      * call {@link #grantTrust(CharSequence, long, boolean)} if the trust state should be
348      * continued.
349      */
onTrustTimeout()350     public void onTrustTimeout() {
351     }
352 
353     /**
354      * Called when the device enters a state where a PIN, pattern or
355      * password must be entered to unlock it.
356      */
onDeviceLocked()357     public void onDeviceLocked() {
358     }
359 
360     /**
361      * Called when the device leaves a state where a PIN, pattern or
362      * password must be entered to unlock it.
363      */
onDeviceUnlocked()364     public void onDeviceUnlocked() {
365     }
366 
367     /**
368      * Called when the device enters a temporary unlock lockout.
369      *
370      * <p>This occurs when the user has consecutively failed to unlock the device too many times,
371      * and must wait until a timeout has passed to perform another attempt. The user may then only
372      * use strong authentication mechanisms (PIN, pattern or password) to unlock the device.
373      * Calls to {@link #grantTrust(CharSequence, long, int)} will be ignored until the user has
374      * unlocked the device and {@link #onDeviceUnlocked()} is called.
375      *
376      * @param timeoutMs The amount of time, in milliseconds, that needs to elapse before the user
377      *    can attempt to unlock the device again.
378      */
onDeviceUnlockLockout(long timeoutMs)379     public void onDeviceUnlockLockout(long timeoutMs) {
380     }
381 
382     /**
383      * Called when an escrow token is added for user userId.
384      *
385      * @param token the added token
386      * @param handle the handle to the corresponding internal synthetic password. A user is unlocked
387      * by presenting both handle and escrow token.
388      * @param user the user to which the escrow token is added.
389      *
390      */
onEscrowTokenAdded(byte[] token, long handle, UserHandle user)391     public void onEscrowTokenAdded(byte[] token, long handle, UserHandle user) {
392     }
393 
394     /**
395      * Called when an escrow token state is received upon request.
396      *
397      * @param handle the handle to the internal synthetic password.
398      * @param state the state of the requested escrow token, see {@link TokenState}.
399      *
400      */
onEscrowTokenStateReceived(long handle, @TokenState int tokenState)401     public void onEscrowTokenStateReceived(long handle, @TokenState int tokenState) {
402     }
403 
404     /**
405      * Called when an escrow token is removed.
406      *
407      * @param handle the handle to the removed the synthetic password.
408      * @param successful whether the removing operaiton is achieved.
409      *
410      */
onEscrowTokenRemoved(long handle, boolean successful)411     public void onEscrowTokenRemoved(long handle, boolean successful) {
412     }
413 
onError(String msg)414     private void onError(String msg) {
415         Slog.v(TAG, "Remote exception while " + msg);
416     }
417 
418     /**
419      * Called when device policy admin wants to enable specific options for agent in response to
420      * {@link DevicePolicyManager#setKeyguardDisabledFeatures(ComponentName, int)} and
421      * {@link DevicePolicyManager#setTrustAgentConfiguration(ComponentName, ComponentName,
422      * PersistableBundle)}.
423      * <p>Agents that support configuration options should overload this method and return 'true'.
424      *
425      * @param options The aggregated list of options or an empty list if no restrictions apply.
426      * @return true if it supports configuration options.
427      */
onConfigure(List<PersistableBundle> options)428     public boolean onConfigure(List<PersistableBundle> options) {
429         return false;
430     }
431 
432     /**
433      * Attempts to grant trust on the device.
434      *
435      * @param initiatedByUser see {@link #FLAG_GRANT_TRUST_INITIATED_BY_USER}
436      * @deprecated use {@link #grantTrust(CharSequence, long, int, Consumer)} instead.
437      */
438     @Deprecated
grantTrust( final CharSequence message, final long durationMs, final boolean initiatedByUser)439     public final void grantTrust(
440             final CharSequence message, final long durationMs, final boolean initiatedByUser) {
441         grantTrust(message, durationMs, initiatedByUser ? FLAG_GRANT_TRUST_INITIATED_BY_USER : 0);
442     }
443 
444     /**
445      * Attempts to grant trust on the device.
446      * @deprecated use {@link #grantTrust(CharSequence, long, int, Consumer)} instead.
447      */
448     @Deprecated
grantTrust( final CharSequence message, final long durationMs, @GrantTrustFlags final int flags)449     public final void grantTrust(
450             final CharSequence message, final long durationMs, @GrantTrustFlags final int flags) {
451         grantTrust(message, durationMs, flags, null);
452     }
453 
454     /**
455      * Attempts to grant trust on the device.
456      *
457      * @param message describes why the device is trusted, e.g. "Trusted by location".
458      * @param durationMs amount of time in milliseconds to keep the device in a trusted state.
459      *    Trust for this agent will automatically be revoked when the timeout expires unless
460      *    extended by a subsequent call to this function. The timeout is measured from the
461      *    invocation of this function as dictated by {@link SystemClock#elapsedRealtime())}.
462      *    For security reasons, the value should be no larger than necessary.
463      *    The value may be adjusted by the system as necessary to comply with a policy controlled
464      *    by the system or {@link DevicePolicyManager} restrictions. See {@link #onTrustTimeout()}
465      *    for determining when trust expires.
466      * @param flags flags to control call: see constants prefixed by {@code FLAG_GRANT_TRUST_}.
467      * @param resultCallback may be called with the results of the grant
468      * @throws IllegalStateException if the agent is not currently managing trust.
469      *
470      * See {@link GrantTrustResult} for the cases where {@code resultCallback} will be called.
471      */
grantTrust( @onNull final CharSequence message, final long durationMs, @GrantTrustFlags final int flags, @Nullable final Consumer<GrantTrustResult> resultCallback)472     public final void grantTrust(
473             @NonNull final CharSequence message,
474             final long durationMs,
475             @GrantTrustFlags final int flags,
476             @Nullable final Consumer<GrantTrustResult> resultCallback) {
477         synchronized (mLock) {
478             if (!mManagingTrust) {
479                 throw new IllegalStateException("Cannot grant trust if agent is not managing trust."
480                         + " Call setManagingTrust(true) first.");
481             }
482 
483             // Prepare future for the IPC
484             AndroidFuture<GrantTrustResult> future = new AndroidFuture<>();
485             future.thenAccept(result -> {
486                 if (resultCallback != null) {
487                     // Instead of taking an explicit executor, we post this to mHandler to be
488                     // consistent with the other event methods in this class.
489                     mHandler.post(() -> resultCallback.accept(result));
490                 }
491             });
492 
493             if (mCallback != null) {
494                 try {
495                     mCallback.grantTrust(message.toString(), durationMs, flags, future);
496                 } catch (RemoteException e) {
497                     onError("calling enableTrust()");
498                 }
499             } else {
500                 // Remember trust has been granted so we can effectively grant it once the service
501                 // is bound.
502                 mPendingGrantTrustTask = new Runnable() {
503                     @Override
504                     public void run() {
505                         grantTrust(message, durationMs, flags, resultCallback);
506                     }
507                 };
508             }
509         }
510     }
511 
512     /**
513      * Call to revoke trust on the device.
514      */
revokeTrust()515     public final void revokeTrust() {
516         synchronized (mLock) {
517             if (mPendingGrantTrustTask != null) {
518                 mPendingGrantTrustTask = null;
519             }
520             if (mCallback != null) {
521                 try {
522                     mCallback.revokeTrust();
523                 } catch (RemoteException e) {
524                     onError("calling revokeTrust()");
525                 }
526             }
527         }
528     }
529 
530     /**
531      * Call to notify the system if the agent is ready to manage trust.
532      *
533      * This property is not persistent across recreating the service and defaults to false.
534      * Therefore this method is typically called when initializing the agent in {@link #onCreate}.
535      *
536      * @param managingTrust indicates if the agent would like to manage trust.
537      */
setManagingTrust(boolean managingTrust)538     public final void setManagingTrust(boolean managingTrust) {
539         synchronized (mLock) {
540             if (mManagingTrust != managingTrust) {
541                 mManagingTrust = managingTrust;
542                 if (mCallback != null) {
543                     try {
544                         mCallback.setManagingTrust(managingTrust);
545                     } catch (RemoteException e) {
546                         onError("calling setManagingTrust()");
547                     }
548                 }
549             }
550         }
551     }
552 
553     /**
554      * Call to add an escrow token to derive a synthetic password. A synthetic password is an
555      * alternaive to the user-set password/pin/pattern in order to unlock encrypted disk. An escrow
556      * token can be taken and internally derive the synthetic password. The new added token will not
557      * be acivated until the user input the correct PIN/Passcode/Password once.
558      *
559      * Result will be return by callback {@link #onEscrowTokenAdded(long, int)}
560      *
561      * @param token an escrow token of high entropy.
562      * @param user the user which the escrow token will be added to.
563      *
564      */
addEscrowToken(byte[] token, UserHandle user)565     public final void addEscrowToken(byte[] token, UserHandle user) {
566         synchronized (mLock) {
567             if (mCallback == null) {
568                 Slog.w(TAG, "Cannot add escrow token if the agent is not connecting to framework");
569                 throw new IllegalStateException("Trust agent is not connected");
570             }
571             try {
572                 mCallback.addEscrowToken(token, user.getIdentifier());
573             } catch (RemoteException e) {
574                 onError("calling addEscrowToken");
575             }
576         }
577     }
578 
579     /**
580      * Call to check the active state of an escrow token.
581      *
582      * Result will be return in callback {@link #onEscrowTokenStateReceived(long, boolean)}
583      *
584      * @param handle the handle of escrow token to the internal synthetic password.
585      * @param user the user which the escrow token is added to.
586      *
587      */
isEscrowTokenActive(long handle, UserHandle user)588     public final void isEscrowTokenActive(long handle, UserHandle user) {
589         synchronized (mLock) {
590             if (mCallback == null) {
591                 Slog.w(TAG, "Cannot add escrow token if the agent is not connecting to framework");
592                 throw new IllegalStateException("Trust agent is not connected");
593             }
594             try {
595                 mCallback.isEscrowTokenActive(handle, user.getIdentifier());
596             } catch (RemoteException e) {
597                 onError("calling isEscrowTokenActive");
598             }
599         }
600     }
601 
602     /**
603      * Call to remove the escrow token.
604      *
605      * Result will be return in callback {@link #onEscrowTokenRemoved(long, boolean)}
606      *
607      * @param handle the handle of escrow tokent to the internal synthetic password.
608      * @param user the user id which the escrow token is added to.
609      *
610      */
removeEscrowToken(long handle, UserHandle user)611     public final void removeEscrowToken(long handle, UserHandle user) {
612         synchronized (mLock) {
613             if (mCallback == null) {
614                 Slog.w(TAG, "Cannot add escrow token if the agent is not connecting to framework");
615                 throw new IllegalStateException("Trust agent is not connected");
616             }
617             try {
618                 mCallback.removeEscrowToken(handle, user.getIdentifier());
619             } catch (RemoteException e) {
620                 onError("callling removeEscrowToken");
621             }
622         }
623     }
624 
625     /**
626      * Call to unlock user's FBE.
627      *
628      * @param handle the handle of escrow tokent to the internal synthetic password.
629      * @param token the escrow token
630      * @param user the user about to be unlocked.
631      *
632      */
unlockUserWithToken(long handle, byte[] token, UserHandle user)633     public final void unlockUserWithToken(long handle, byte[] token, UserHandle user) {
634         UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
635         if (um.isUserUnlocked(user)) {
636             Slog.i(TAG, "User already unlocked");
637             return;
638         }
639 
640         synchronized (mLock) {
641             if (mCallback == null) {
642                 Slog.w(TAG, "Cannot add escrow token if the agent is not connecting to framework");
643                 throw new IllegalStateException("Trust agent is not connected");
644             }
645             try {
646                 mCallback.unlockUserWithToken(handle, token, user.getIdentifier());
647             } catch (RemoteException e) {
648                 onError("calling unlockUserWithToken");
649             }
650         }
651     }
652 
653     /**
654      * Locks the user.
655      *
656      * This revokes any trust granted by this agent and shows keyguard for the user if it is not
657      * currently shown for them. Other users are not affected. Note that this is in contrast to
658      * {@link #revokeTrust()} which does not show keyguard if it is not already shown.
659      *
660      * If the user has no auth method specified, then keyguard will still be shown but can be
661      * dismissed normally.
662      */
lockUser()663     public final void lockUser() {
664         if (mCallback != null) {
665             try {
666                 mCallback.lockUser();
667             } catch (RemoteException e) {
668                 onError("calling lockUser");
669             }
670         }
671     }
672 
673     /**
674      * Request showing a transient error message on the keyguard.
675      * The message will be visible on the lock screen or always on display if possible but can be
676      * overridden by other keyguard events of higher priority - eg. fingerprint auth error.
677      * Other trust agents may override your message if posted simultaneously.
678      *
679      * @param message Message to show.
680      */
showKeyguardErrorMessage(@onNull CharSequence message)681     public final void showKeyguardErrorMessage(@NonNull CharSequence message) {
682         if (message == null) {
683             throw new IllegalArgumentException("message cannot be null");
684         }
685         synchronized (mLock) {
686             if (mCallback == null) {
687                 Slog.w(TAG, "Cannot show message because service is not connected to framework.");
688                 throw new IllegalStateException("Trust agent is not connected");
689             }
690             try {
691                 mCallback.showKeyguardErrorMessage(message);
692             } catch (RemoteException e) {
693                 onError("calling showKeyguardErrorMessage");
694             }
695         }
696     }
697 
698     @Override
onBind(Intent intent)699     public final IBinder onBind(Intent intent) {
700         if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
701         return new TrustAgentServiceWrapper();
702     }
703 
704     private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub {
705         @Override /* Binder API */
onUnlockAttempt(boolean successful)706         public void onUnlockAttempt(boolean successful) {
707             mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0).sendToTarget();
708         }
709 
710         @Override
onUserRequestedUnlock(boolean dismissKeyguard)711         public void onUserRequestedUnlock(boolean dismissKeyguard) {
712             mHandler.obtainMessage(MSG_USER_REQUESTED_UNLOCK, dismissKeyguard ? 1 : 0, 0)
713                     .sendToTarget();
714         }
715 
716         @Override
onUserMayRequestUnlock()717         public void onUserMayRequestUnlock() {
718             mHandler.obtainMessage(MSG_USER_MAY_REQUEST_UNLOCK).sendToTarget();
719         }
720 
721         @Override
onUnlockLockout(int timeoutMs)722         public void onUnlockLockout(int timeoutMs) {
723             mHandler.obtainMessage(MSG_UNLOCK_LOCKOUT, timeoutMs, 0).sendToTarget();
724         }
725 
726         @Override /* Binder API */
onTrustTimeout()727         public void onTrustTimeout() {
728             mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT);
729         }
730 
731         @Override /* Binder API */
onConfigure(List<PersistableBundle> args, IBinder token)732         public void onConfigure(List<PersistableBundle> args, IBinder token) {
733             mHandler.obtainMessage(MSG_CONFIGURE, new ConfigurationData(args, token))
734                     .sendToTarget();
735         }
736 
737         @Override
onDeviceLocked()738         public void onDeviceLocked() throws RemoteException {
739             mHandler.obtainMessage(MSG_DEVICE_LOCKED).sendToTarget();
740         }
741 
742         @Override
onDeviceUnlocked()743         public void onDeviceUnlocked() throws RemoteException {
744             mHandler.obtainMessage(MSG_DEVICE_UNLOCKED).sendToTarget();
745         }
746 
747         @Override /* Binder API */
setCallback(ITrustAgentServiceCallback callback)748         public void setCallback(ITrustAgentServiceCallback callback) {
749             synchronized (mLock) {
750                 mCallback = callback;
751                 // The managingTrust property is false implicitly on the server-side, so we only
752                 // need to set it here if the agent has decided to manage trust.
753                 if (mManagingTrust) {
754                     try {
755                         mCallback.setManagingTrust(mManagingTrust);
756                     } catch (RemoteException e ) {
757                         onError("calling setManagingTrust()");
758                     }
759                 }
760                 if (mPendingGrantTrustTask != null) {
761                     mPendingGrantTrustTask.run();
762                     mPendingGrantTrustTask = null;
763                 }
764             }
765         }
766 
767         @Override
onEscrowTokenAdded(byte[] token, long handle, UserHandle user)768         public void onEscrowTokenAdded(byte[] token, long handle, UserHandle user) {
769             Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_ADDED);
770             msg.getData().putByteArray(EXTRA_TOKEN, token);
771             msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
772             msg.getData().putParcelable(EXTRA_USER_HANDLE, user);
773             msg.sendToTarget();
774         }
775 
onTokenStateReceived(long handle, int tokenState)776         public void onTokenStateReceived(long handle, int tokenState) {
777             Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_STATE_RECEIVED);
778             msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
779             msg.getData().putInt(EXTRA_TOKEN_STATE, tokenState);
780             msg.sendToTarget();
781         }
782 
onEscrowTokenRemoved(long handle, boolean successful)783         public void onEscrowTokenRemoved(long handle, boolean successful) {
784             Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_REMOVED);
785             msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
786             msg.getData().putBoolean(EXTRA_TOKEN_REMOVED_RESULT, successful);
787             msg.sendToTarget();
788         }
789     }
790 }
791