TrustAgentWrapper.java revision 7d59b4f981e24a4a446522e9b8d3d6a7115c1459
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 17package com.android.server.trust; 18 19import android.content.ComponentName; 20import android.content.Context; 21import android.content.Intent; 22import android.content.ServiceConnection; 23import android.os.Handler; 24import android.os.IBinder; 25import android.os.Message; 26import android.os.RemoteException; 27import android.os.UserHandle; 28import android.util.Log; 29import android.util.Slog; 30import android.service.trust.ITrustAgentService; 31import android.service.trust.ITrustAgentServiceCallback; 32 33/** 34 * A wrapper around a TrustAgentService interface. Coordinates communication between 35 * TrustManager and the actual TrustAgent. 36 */ 37public class TrustAgentWrapper { 38 private static final boolean DEBUG = false; 39 private static final String TAG = "TrustAgentWrapper"; 40 41 private static final int MSG_GRANT_TRUST = 1; 42 private static final int MSG_REVOKE_TRUST = 2; 43 private static final int MSG_TRUST_TIMEOUT = 3; 44 45 /** 46 * Long extra for {@link #MSG_GRANT_TRUST} 47 */ 48 private static final String DATA_DURATION = "duration"; 49 50 private final TrustManagerService mTrustManagerService; 51 private final int mUserId; 52 private final Context mContext; 53 private final ComponentName mName; 54 55 private ITrustAgentService mTrustAgentService; 56 57 // Trust state 58 private boolean mTrusted; 59 private CharSequence mMessage; 60 61 private final Handler mHandler = new Handler() { 62 @Override 63 public void handleMessage(Message msg) { 64 switch (msg.what) { 65 case MSG_GRANT_TRUST: 66 if (!isConnected()) { 67 Log.w(TAG, "Agent is not connected, cannot grant trust: " 68 + mName.flattenToShortString()); 69 return; 70 } 71 mTrusted = true; 72 mMessage = (CharSequence) msg.obj; 73 boolean initiatedByUser = msg.arg1 != 0; 74 // TODO: Handle initiatedByUser. 75 long durationMs = msg.getData().getLong(DATA_DURATION); 76 if (durationMs > 0) { 77 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 78 mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs); 79 } 80 mTrustManagerService.mArchive.logGrantTrust(mUserId, mName, 81 (mMessage != null ? mMessage.toString() : null), 82 durationMs, initiatedByUser); 83 mTrustManagerService.updateTrust(mUserId); 84 break; 85 case MSG_TRUST_TIMEOUT: 86 if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString()); 87 mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName); 88 // Fall through. 89 case MSG_REVOKE_TRUST: 90 mTrusted = false; 91 mMessage = null; 92 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 93 if (msg.what == MSG_REVOKE_TRUST) { 94 mTrustManagerService.mArchive.logRevokeTrust(mUserId, mName); 95 } 96 mTrustManagerService.updateTrust(mUserId); 97 break; 98 } 99 } 100 }; 101 102 private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() { 103 104 @Override 105 public void grantTrust(CharSequence userMessage, long durationMs, boolean initiatedByUser) { 106 if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs 107 + ", initiatedByUser = " + initiatedByUser + ")"); 108 109 Message msg = mHandler.obtainMessage( 110 MSG_GRANT_TRUST, initiatedByUser ? 1 : 0, 0, userMessage); 111 msg.getData().putLong(DATA_DURATION, durationMs); 112 msg.sendToTarget(); 113 } 114 115 @Override 116 public void revokeTrust() { 117 if (DEBUG) Slog.v(TAG, "revokeTrust()"); 118 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 119 } 120 }; 121 122 private final ServiceConnection mConnection = new ServiceConnection() { 123 @Override 124 public void onServiceConnected(ComponentName name, IBinder service) { 125 if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString()); 126 mTrustAgentService = ITrustAgentService.Stub.asInterface(service); 127 mTrustManagerService.mArchive.logAgentConnected(mUserId, name); 128 setCallback(mCallback); 129 } 130 131 @Override 132 public void onServiceDisconnected(ComponentName name) { 133 if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString()); 134 mTrustAgentService = null; 135 mTrustManagerService.mArchive.logAgentDied(mUserId, name); 136 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 137 } 138 }; 139 140 141 public TrustAgentWrapper(Context context, TrustManagerService trustManagerService, 142 Intent intent, UserHandle user) { 143 mContext = context; 144 mTrustManagerService = trustManagerService; 145 mUserId = user.getIdentifier(); 146 mName = intent.getComponent(); 147 if (!context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user)) { 148 if (DEBUG) Log.v(TAG, "can't bind to TrustAgent " + mName.flattenToShortString()); 149 // TODO: retry somehow? 150 } 151 } 152 153 private void onError(Exception e) { 154 Slog.w(TAG , "Remote Exception", e); 155 } 156 157 /** 158 * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean) 159 */ 160 public void onUnlockAttempt(boolean successful) { 161 try { 162 if (mTrustAgentService != null) mTrustAgentService.onUnlockAttempt(successful); 163 } catch (RemoteException e) { 164 onError(e); 165 } 166 } 167 168 private void setCallback(ITrustAgentServiceCallback callback) { 169 try { 170 if (mTrustAgentService != null) { 171 mTrustAgentService.setCallback(callback); 172 } 173 } catch (RemoteException e) { 174 onError(e); 175 } 176 } 177 178 public boolean isTrusted() { 179 return mTrusted; 180 } 181 182 public CharSequence getMessage() { 183 return mMessage; 184 } 185 186 public void unbind() { 187 if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString()); 188 mTrustManagerService.mArchive.logAgentStopped(mUserId, mName); 189 mContext.unbindService(mConnection); 190 mTrustAgentService = null; 191 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 192 } 193 194 public boolean isConnected() { 195 return mTrustAgentService != null; 196 } 197} 198