TrustAgentWrapper.java revision 7e03dfcb796ef1a6000a5fd5fda03c9e15ea62e1
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.Bundle;
24import android.os.Handler;
25import android.os.IBinder;
26import android.os.Message;
27import android.os.RemoteException;
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_ENABLE_TRUST = 1;
43    private static final int MSG_REVOKE_TRUST = 2;
44    private static final int MSG_TRUST_TIMEOUT = 3;
45
46    private final TrustManagerService mTrustManagerService;
47    private final int mUserId;
48    private final Context mContext;
49    private final ComponentName mName;
50
51    private ITrustAgentService mTrustAgentService;
52
53    // Trust state
54    private boolean mTrusted;
55    private CharSequence mMessage;
56
57    private final Handler mHandler = new Handler() {
58        @Override
59        public void handleMessage(Message msg) {
60            switch (msg.what) {
61                case MSG_ENABLE_TRUST:
62                    mTrusted = true;
63                    mMessage = (CharSequence) msg.obj;
64                    boolean initiatedByUser = msg.arg1 != 0;
65                    // TODO: Handle handle user initiated trust changes.
66                    mTrustManagerService.updateTrust(mUserId);
67                    break;
68                case MSG_TRUST_TIMEOUT:
69                    if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString());
70                    // Fall through.
71                case MSG_REVOKE_TRUST:
72                    mTrusted = false;
73                    mMessage = null;
74                    mTrustManagerService.updateTrust(mUserId);
75                    break;
76            }
77        }
78    };
79
80    private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() {
81
82        @Override
83        public void grantTrust(CharSequence userMessage, long durationMs, boolean initiatedByUser) {
84            if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs
85                        + ", initiatedByUser = " + initiatedByUser + ")");
86
87            mHandler.obtainMessage(MSG_ENABLE_TRUST, initiatedByUser ? 1 : 0, 0, userMessage)
88                    .sendToTarget();
89            if (durationMs > 0) {
90                mHandler.removeMessages(MSG_TRUST_TIMEOUT);
91                mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs);
92            }
93        }
94
95        @Override
96        public void revokeTrust() {
97            if (DEBUG) Slog.v(TAG, "revokeTrust()");
98            mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
99        }
100    };
101
102    private final ServiceConnection mConnection = new ServiceConnection() {
103        @Override
104        public void onServiceConnected(ComponentName name, IBinder service) {
105            if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString());
106            mTrustAgentService = ITrustAgentService.Stub.asInterface(service);
107            setCallback(mCallback);
108        }
109
110        @Override
111        public void onServiceDisconnected(ComponentName name) {
112            if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString());
113            mTrustAgentService = null;
114            mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
115        }
116    };
117
118
119    public TrustAgentWrapper(Context context, TrustManagerService trustManagerService,
120            Intent intent, UserHandle user) {
121        mContext = context;
122        mTrustManagerService = trustManagerService;
123        mUserId = user.getIdentifier();
124        mName = intent.getComponent();
125        if (!context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user)) {
126            if (DEBUG) Log.v(TAG, "can't bind to TrustAgent " + mName.flattenToShortString());
127            // TODO: retry somehow?
128        }
129    }
130
131    private void onError(Exception e) {
132        Slog.w(TAG , "Remote Exception", e);
133    }
134
135    /**
136     * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
137     */
138    public void onUnlockAttempt(boolean successful) {
139        try {
140            if (mTrustAgentService != null) mTrustAgentService.onUnlockAttempt(successful);
141        } catch (RemoteException e) {
142            onError(e);
143        }
144    }
145
146    private void setCallback(ITrustAgentServiceCallback callback) {
147        try {
148            if (mTrustAgentService != null) {
149                mTrustAgentService.setCallback(callback);
150            }
151        } catch (RemoteException e) {
152            onError(e);
153        }
154    }
155
156    public boolean isTrusted() {
157        return mTrusted;
158    }
159
160    public CharSequence getMessage() {
161        return mMessage;
162    }
163
164    public void unbind() {
165        if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString());
166        mContext.unbindService(mConnection);
167    }
168}
169