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