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