• Home
  • History
  • Annotate
  • 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.SdkConstant;
22 import android.annotation.SystemApi;
23 import android.app.Service;
24 import android.app.admin.DevicePolicyManager;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ServiceInfo;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.IBinder;
33 import android.os.Message;
34 import android.os.PersistableBundle;
35 import android.os.RemoteException;
36 import android.os.UserHandle;
37 import android.os.UserManager;
38 import android.util.Log;
39 import android.util.Slog;
40 import java.lang.annotation.Retention;
41 import java.lang.annotation.RetentionPolicy;
42 import java.util.List;
43 
44 /**
45  * A service that notifies the system about whether it believes the environment of the device
46  * to be trusted.
47  *
48  * <p>Trust agents may only be provided by the platform. It is expected that there is only
49  * one trust agent installed on the platform. In the event there is more than one,
50  * either trust agent can enable trust.
51  * </p>
52  *
53  * <p>To extend this class, you must declare the service in your manifest file with
54  * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission
55  * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
56  * <pre>
57  * &lt;service android:name=".TrustAgent"
58  *          android:label="&#64;string/service_name"
59  *          android:permission="android.permission.BIND_TRUST_AGENT">
60  *     &lt;intent-filter>
61  *         &lt;action android:name="android.service.trust.TrustAgentService" />
62  *     &lt;/intent-filter>
63  *     &lt;meta-data android:name="android.service.trust.trustagent"
64  *          android:value="&#64;xml/trust_agent" />
65  * &lt;/service></pre>
66  *
67  * <p>The associated meta-data file can specify an activity that is accessible through Settings
68  * and should allow configuring the trust agent, as defined in
69  * {@link android.R.styleable#TrustAgent}. For example:</p>
70  *
71  * <pre>
72  * &lt;trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
73  *          android:settingsActivity=".TrustAgentSettings" /></pre>
74  *
75  * @hide
76  */
77 @SystemApi
78 public class TrustAgentService extends Service {
79 
80     private final String TAG = TrustAgentService.class.getSimpleName() +
81             "[" + getClass().getSimpleName() + "]";
82     private static final boolean DEBUG = false;
83 
84     /**
85      * The {@link Intent} that must be declared as handled by the service.
86      */
87     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
88     public static final String SERVICE_INTERFACE
89             = "android.service.trust.TrustAgentService";
90 
91     /**
92      * The name of the {@code meta-data} tag pointing to additional configuration of the trust
93      * agent.
94      */
95     public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
96 
97 
98     /**
99      * Flag for {@link #grantTrust(CharSequence, long, int)} indicating that trust is being granted
100      * as the direct result of user action - such as solving a security challenge. The hint is used
101      * by the system to optimize the experience. Behavior may vary by device and release, so
102      * one should only set this parameter if it meets the above criteria rather than relying on
103      * the behavior of any particular device or release.
104      */
105     public static final int FLAG_GRANT_TRUST_INITIATED_BY_USER = 1 << 0;
106 
107     /**
108      * Flag for {@link #grantTrust(CharSequence, long, int)} indicating that the agent would like
109      * to dismiss the keyguard. When using this flag, the {@code TrustAgentService} must ensure
110      * it is only set in response to a direct user action with the expectation of dismissing the
111      * keyguard.
112      */
113     public static final int FLAG_GRANT_TRUST_DISMISS_KEYGUARD = 1 << 1;
114 
115     /** @hide */
116     @Retention(RetentionPolicy.SOURCE)
117     @IntDef(flag = true,
118             value = {
119                     FLAG_GRANT_TRUST_INITIATED_BY_USER,
120                     FLAG_GRANT_TRUST_DISMISS_KEYGUARD,
121             })
122     public @interface GrantTrustFlags {}
123 
124 
125     /**
126      * Int enum indicating that escrow token is active.
127      * See {@link #onEscrowTokenStateReceived(long, int)}
128      *
129      */
130     public static final int TOKEN_STATE_ACTIVE = 1;
131 
132     /**
133      * Int enum indicating that escow token is inactive.
134      * See {@link #onEscrowTokenStateReceived(long, int)}
135      *
136      */
137     public static final int TOKEN_STATE_INACTIVE = 0;
138 
139     /** @hide */
140     @Retention(RetentionPolicy.SOURCE)
141     @IntDef(flag = true,
142             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()) {
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     @Override
onBind(Intent intent)567     public final IBinder onBind(Intent intent) {
568         if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
569         return new TrustAgentServiceWrapper();
570     }
571 
572     private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub {
573         @Override /* Binder API */
onUnlockAttempt(boolean successful)574         public void onUnlockAttempt(boolean successful) {
575             mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0).sendToTarget();
576         }
577 
578         @Override
onUnlockLockout(int timeoutMs)579         public void onUnlockLockout(int timeoutMs) {
580             mHandler.obtainMessage(MSG_UNLOCK_LOCKOUT, timeoutMs, 0).sendToTarget();
581         }
582 
583         @Override /* Binder API */
onTrustTimeout()584         public void onTrustTimeout() {
585             mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT);
586         }
587 
588         @Override /* Binder API */
onConfigure(List<PersistableBundle> args, IBinder token)589         public void onConfigure(List<PersistableBundle> args, IBinder token) {
590             mHandler.obtainMessage(MSG_CONFIGURE, new ConfigurationData(args, token))
591                     .sendToTarget();
592         }
593 
594         @Override
onDeviceLocked()595         public void onDeviceLocked() throws RemoteException {
596             mHandler.obtainMessage(MSG_DEVICE_LOCKED).sendToTarget();
597         }
598 
599         @Override
onDeviceUnlocked()600         public void onDeviceUnlocked() throws RemoteException {
601             mHandler.obtainMessage(MSG_DEVICE_UNLOCKED).sendToTarget();
602         }
603 
604         @Override /* Binder API */
setCallback(ITrustAgentServiceCallback callback)605         public void setCallback(ITrustAgentServiceCallback callback) {
606             synchronized (mLock) {
607                 mCallback = callback;
608                 // The managingTrust property is false implicitly on the server-side, so we only
609                 // need to set it here if the agent has decided to manage trust.
610                 if (mManagingTrust) {
611                     try {
612                         mCallback.setManagingTrust(mManagingTrust);
613                     } catch (RemoteException e ) {
614                         onError("calling setManagingTrust()");
615                     }
616                 }
617                 if (mPendingGrantTrustTask != null) {
618                     mPendingGrantTrustTask.run();
619                     mPendingGrantTrustTask = null;
620                 }
621             }
622         }
623 
624         @Override
onEscrowTokenAdded(byte[] token, long handle, UserHandle user)625         public void onEscrowTokenAdded(byte[] token, long handle, UserHandle user) {
626             Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_ADDED);
627             msg.getData().putByteArray(EXTRA_TOKEN, token);
628             msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
629             msg.getData().putParcelable(EXTRA_USER_HANDLE, user);
630             msg.sendToTarget();
631         }
632 
onTokenStateReceived(long handle, int tokenState)633         public void onTokenStateReceived(long handle, int tokenState) {
634             Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_STATE_RECEIVED);
635             msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
636             msg.getData().putInt(EXTRA_TOKEN_STATE, tokenState);
637             msg.sendToTarget();
638         }
639 
onEscrowTokenRemoved(long handle, boolean successful)640         public void onEscrowTokenRemoved(long handle, boolean successful) {
641             Message msg = mHandler.obtainMessage(MSG_ESCROW_TOKEN_REMOVED);
642             msg.getData().putLong(EXTRA_TOKEN_HANDLE, handle);
643             msg.getData().putBoolean(EXTRA_TOKEN_REMOVED_RESULT, successful);
644             msg.sendToTarget();
645         }
646     }
647 }
648