TrustAgentWrapper.java revision c5f95cea2639b698594a85acbde6a5519941d7b1
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.SystemClock; 28import android.os.UserHandle; 29import android.util.Log; 30import android.util.Slog; 31import android.service.trust.ITrustAgentService; 32import android.service.trust.ITrustAgentServiceCallback; 33 34/** 35 * A wrapper around a TrustAgentService interface. Coordinates communication between 36 * TrustManager and the actual TrustAgent. 37 */ 38public class TrustAgentWrapper { 39 private static final boolean DEBUG = false; 40 private static final String TAG = "TrustAgentWrapper"; 41 42 private static final int MSG_GRANT_TRUST = 1; 43 private static final int MSG_REVOKE_TRUST = 2; 44 private static final int MSG_TRUST_TIMEOUT = 3; 45 private static final int MSG_RESTART_TIMEOUT = 4; 46 47 /** 48 * Time in uptime millis that we wait for the service connection, both when starting 49 * and when the service disconnects. 50 */ 51 private static final long RESTART_TIMEOUT_MILLIS = 5 * 60000; 52 53 /** 54 * Long extra for {@link #MSG_GRANT_TRUST} 55 */ 56 private static final String DATA_DURATION = "duration"; 57 58 private final TrustManagerService mTrustManagerService; 59 private final int mUserId; 60 private final Context mContext; 61 private final ComponentName mName; 62 63 private ITrustAgentService mTrustAgentService; 64 private boolean mBound; 65 private long mScheduledRestartUptimeMillis; 66 67 // Trust state 68 private boolean mTrusted; 69 private CharSequence mMessage; 70 71 private final Handler mHandler = new Handler() { 72 @Override 73 public void handleMessage(Message msg) { 74 switch (msg.what) { 75 case MSG_GRANT_TRUST: 76 if (!isConnected()) { 77 Log.w(TAG, "Agent is not connected, cannot grant trust: " 78 + mName.flattenToShortString()); 79 return; 80 } 81 mTrusted = true; 82 mMessage = (CharSequence) msg.obj; 83 boolean initiatedByUser = msg.arg1 != 0; 84 // TODO: Handle initiatedByUser. 85 long durationMs = msg.getData().getLong(DATA_DURATION); 86 if (durationMs > 0) { 87 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 88 mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs); 89 } 90 mTrustManagerService.mArchive.logGrantTrust(mUserId, mName, 91 (mMessage != null ? mMessage.toString() : null), 92 durationMs, initiatedByUser); 93 mTrustManagerService.updateTrust(mUserId); 94 break; 95 case MSG_TRUST_TIMEOUT: 96 if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString()); 97 mTrustManagerService.mArchive.logTrustTimeout(mUserId, mName); 98 // Fall through. 99 case MSG_REVOKE_TRUST: 100 mTrusted = false; 101 mMessage = null; 102 mHandler.removeMessages(MSG_TRUST_TIMEOUT); 103 if (msg.what == MSG_REVOKE_TRUST) { 104 mTrustManagerService.mArchive.logRevokeTrust(mUserId, mName); 105 } 106 mTrustManagerService.updateTrust(mUserId); 107 break; 108 case MSG_RESTART_TIMEOUT: 109 unbind(); 110 mTrustManagerService.resetAgent(mName, mUserId); 111 break; 112 } 113 } 114 }; 115 116 private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() { 117 118 @Override 119 public void grantTrust(CharSequence userMessage, long durationMs, boolean initiatedByUser) { 120 if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs 121 + ", initiatedByUser = " + initiatedByUser + ")"); 122 123 Message msg = mHandler.obtainMessage( 124 MSG_GRANT_TRUST, initiatedByUser ? 1 : 0, 0, userMessage); 125 msg.getData().putLong(DATA_DURATION, durationMs); 126 msg.sendToTarget(); 127 } 128 129 @Override 130 public void revokeTrust() { 131 if (DEBUG) Slog.v(TAG, "revokeTrust()"); 132 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 133 } 134 }; 135 136 private final ServiceConnection mConnection = new ServiceConnection() { 137 @Override 138 public void onServiceConnected(ComponentName name, IBinder service) { 139 if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString()); 140 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 141 mTrustAgentService = ITrustAgentService.Stub.asInterface(service); 142 mTrustManagerService.mArchive.logAgentConnected(mUserId, name); 143 setCallback(mCallback); 144 } 145 146 @Override 147 public void onServiceDisconnected(ComponentName name) { 148 if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString()); 149 mTrustAgentService = null; 150 mTrustManagerService.mArchive.logAgentDied(mUserId, name); 151 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 152 if (mBound) { 153 scheduleRestart(); 154 } 155 } 156 }; 157 158 159 public TrustAgentWrapper(Context context, TrustManagerService trustManagerService, 160 Intent intent, UserHandle user) { 161 mContext = context; 162 mTrustManagerService = trustManagerService; 163 mUserId = user.getIdentifier(); 164 mName = intent.getComponent(); 165 // Schedules a restart for when connecting times out. If the connection succeeds, 166 // the restart is canceled in mCallback's onConnected. 167 scheduleRestart(); 168 mBound = context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user); 169 if (!mBound) { 170 Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString()); 171 } 172 } 173 174 private void onError(Exception e) { 175 Slog.w(TAG , "Remote Exception", e); 176 } 177 178 /** 179 * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean) 180 */ 181 public void onUnlockAttempt(boolean successful) { 182 try { 183 if (mTrustAgentService != null) mTrustAgentService.onUnlockAttempt(successful); 184 } catch (RemoteException e) { 185 onError(e); 186 } 187 } 188 189 private void setCallback(ITrustAgentServiceCallback callback) { 190 try { 191 if (mTrustAgentService != null) { 192 mTrustAgentService.setCallback(callback); 193 } 194 } catch (RemoteException e) { 195 onError(e); 196 } 197 } 198 199 public boolean isTrusted() { 200 return mTrusted; 201 } 202 203 public CharSequence getMessage() { 204 return mMessage; 205 } 206 207 public void unbind() { 208 if (!mBound) { 209 return; 210 } 211 if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString()); 212 mTrustManagerService.mArchive.logAgentStopped(mUserId, mName); 213 mContext.unbindService(mConnection); 214 mBound = false; 215 mTrustAgentService = null; 216 mHandler.sendEmptyMessage(MSG_REVOKE_TRUST); 217 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 218 } 219 220 public boolean isConnected() { 221 return mTrustAgentService != null; 222 } 223 224 public boolean isBound() { 225 return mBound; 226 } 227 228 /** 229 * If not connected, returns the time at which the agent is restarted. 230 * 231 * @return restart time in uptime millis. 232 */ 233 public long getScheduledRestartUptimeMillis() { 234 return mScheduledRestartUptimeMillis; 235 } 236 237 private void scheduleRestart() { 238 mHandler.removeMessages(MSG_RESTART_TIMEOUT); 239 mScheduledRestartUptimeMillis = SystemClock.uptimeMillis() + RESTART_TIMEOUT_MILLIS; 240 mHandler.sendEmptyMessageAtTime(MSG_RESTART_TIMEOUT, mScheduledRestartUptimeMillis); 241 } 242} 243