Home | History | Annotate | Download | only in trust
      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;
    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
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    335     public void onEscrowTokenRemoved(long handle, boolean successful) {
    336     }
    337 
    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      */
    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
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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
    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 */
    599         public void onUnlockAttempt(boolean successful) {
    600             mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0).sendToTarget();
    601         }
    602 
    603         @Override
    604         public void onUnlockLockout(int timeoutMs) {
    605             mHandler.obtainMessage(MSG_UNLOCK_LOCKOUT, timeoutMs, 0).sendToTarget();
    606         }
    607 
    608         @Override /* Binder API */
    609         public void onTrustTimeout() {
    610             mHandler.sendEmptyMessage(MSG_TRUST_TIMEOUT);
    611         }
    612 
    613         @Override /* Binder API */
    614         public void onConfigure(List<PersistableBundle> args, IBinder token) {
    615             mHandler.obtainMessage(MSG_CONFIGURE, new ConfigurationData(args, token))
    616                     .sendToTarget();
    617         }
    618 
    619         @Override
    620         public void onDeviceLocked() throws RemoteException {
    621             mHandler.obtainMessage(MSG_DEVICE_LOCKED).sendToTarget();
    622         }
    623 
    624         @Override
    625         public void onDeviceUnlocked() throws RemoteException {
    626             mHandler.obtainMessage(MSG_DEVICE_UNLOCKED).sendToTarget();
    627         }
    628 
    629         @Override /* Binder API */
    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
    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 
    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 
    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