blob: a83fa877de6c52a9fc9f6e96cb60dfca6abd0481 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.trust;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
import android.service.trust.ITrustAgentService;
import android.service.trust.ITrustAgentServiceCallback;
/**
* A wrapper around a TrustAgentService interface. Coordinates communication between
* TrustManager and the actual TrustAgent.
*/
public class TrustAgentWrapper {
private static final boolean DEBUG = false;
private static final String TAG = "TrustAgentWrapper";
private static final int MSG_ENABLE_TRUST = 1;
private static final int MSG_REVOKE_TRUST = 2;
private static final int MSG_TRUST_TIMEOUT = 3;
private final TrustManagerService mTrustManagerService;
private final int mUserId;
private final Context mContext;
private final ComponentName mName;
private ITrustAgentService mTrustAgentService;
// Trust state
private boolean mTrusted;
private String mMessage;
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ENABLE_TRUST:
mTrusted = true;
mMessage = (String) msg.obj;
boolean initiatedByUser = msg.arg1 != 0;
// TODO: Handle handle user initiated trust changes.
mTrustManagerService.updateTrust(mUserId);
break;
case MSG_TRUST_TIMEOUT:
if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString());
// Fall through.
case MSG_REVOKE_TRUST:
mTrusted = false;
mMessage = null;
mTrustManagerService.updateTrust(mUserId);
break;
}
}
};
private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() {
public void enableTrust(String userMessage, long durationMs, boolean initiatedByUser) {
if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs
+ ", initiatedByUser = " + initiatedByUser + ")");
mHandler.obtainMessage(MSG_ENABLE_TRUST, initiatedByUser ? 1 : 0, 0, userMessage)
.sendToTarget();
if (durationMs > 0) {
mHandler.removeMessages(MSG_TRUST_TIMEOUT);
mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs);
}
}
public void revokeTrust() {
if (DEBUG) Slog.v(TAG, "revokeTrust()");
mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
}
};
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString());
mTrustAgentService = ITrustAgentService.Stub.asInterface(service);
setCallback(mCallback);
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString());
mTrustAgentService = null;
mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
}
};
public TrustAgentWrapper(Context context, TrustManagerService trustManagerService,
Intent intent, UserHandle user) {
mContext = context;
mTrustManagerService = trustManagerService;
mUserId = user.getIdentifier();
mName = intent.getComponent();
if (!context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user)) {
if (DEBUG) Log.v(TAG, "can't bind to TrustAgent " + mName.flattenToShortString());
// TODO: retry somehow?
}
}
private void onError(Exception e) {
Slog.w(TAG , "Remote Exception", e);
}
/**
* @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
*/
public void onUnlockAttempt(boolean successful) {
try {
if (mTrustAgentService != null) mTrustAgentService.onUnlockAttempt(successful);
} catch (RemoteException e) {
onError(e);
}
}
private void setCallback(ITrustAgentServiceCallback callback) {
try {
if (mTrustAgentService != null) {
mTrustAgentService.setCallback(callback);
}
} catch (RemoteException e) {
onError(e);
}
}
public boolean isTrusted() {
return mTrusted;
}
public String getMessage() {
return mMessage;
}
public void unbind() {
if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString());
mContext.unbindService(mConnection);
}
}