TrustAgentService.java revision b803ad3c2cefaba57063385ecab1be27dd2636b0
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 android.service.trust;
18
19import android.Manifest;
20import android.annotation.PrivateApi;
21import android.annotation.SdkConstant;
22import android.app.Service;
23import android.content.ComponentName;
24import android.content.Intent;
25import android.content.pm.PackageManager;
26import android.content.pm.ServiceInfo;
27import android.os.Handler;
28import android.os.IBinder;
29import android.os.RemoteException;
30import android.util.Log;
31import android.util.Slog;
32
33/**
34 * A service that notifies the system about whether it believes the environment of the device
35 * to be trusted.
36 *
37 * <p>Trust agents may only be provided by the platform.</p>
38 *
39 * <p>To extend this class, you must declare the service in your manifest file with
40 * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission
41 * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
42 * <pre>
43 * &lt;service android:name=".TrustAgent"
44 *          android:label="&#64;string/service_name"
45 *          android:permission="android.permission.BIND_TRUST_AGENT">
46 *     &lt;intent-filter>
47 *         &lt;action android:name="android.service.trust.TrustAgentService" />
48 *     &lt;/intent-filter>
49 *     &lt;meta-data android:name="android.service.trust.trustagent"
50 *          android:value="&#64;xml/trust_agent" />
51 * &lt;/service></pre>
52 *
53 * <p>The associated meta-data file can specify an activity that is accessible through Settings
54 * and should allow configuring the trust agent, as defined in
55 * {@link android.R.styleable#TrustAgent}. For example:</p>
56 *
57 * <pre>
58 * &lt;trust-agent xmlns:android="http://schemas.android.com/apk/res/android"
59 *          android:settingsActivity=".TrustAgentSettings" /></pre>
60 *
61 * @hide
62 */
63@PrivateApi
64public class TrustAgentService extends Service {
65    private final String TAG = TrustAgentService.class.getSimpleName() +
66            "[" + getClass().getSimpleName() + "]";
67
68    /**
69     * The {@link Intent} that must be declared as handled by the service.
70     */
71    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
72    public static final String SERVICE_INTERFACE
73            = "android.service.trust.TrustAgentService";
74
75    /**
76     * The name of the {@code meta-data} tag pointing to additional configuration of the trust
77     * agent.
78     */
79    public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
80
81    private static final int MSG_UNLOCK_ATTEMPT = 1;
82
83    private static final boolean DEBUG = false;
84
85    private ITrustAgentServiceCallback mCallback;
86
87    private Handler mHandler = new Handler() {
88        public void handleMessage(android.os.Message msg) {
89            switch (msg.what) {
90                case MSG_UNLOCK_ATTEMPT:
91                    onUnlockAttempt(msg.arg1 != 0);
92                    break;
93            }
94        };
95    };
96
97    @Override
98    public void onCreate() {
99        super.onCreate();
100        ComponentName component = new ComponentName(this, getClass());
101        try {
102            ServiceInfo serviceInfo = getPackageManager().getServiceInfo(component, 0 /* flags */);
103            if (!Manifest.permission.BIND_TRUST_AGENT.equals(serviceInfo.permission)) {
104                throw new IllegalStateException(component.flattenToShortString()
105                        + " is not declared with the permission "
106                        + "\"" + Manifest.permission.BIND_TRUST_AGENT + "\"");
107            }
108        } catch (PackageManager.NameNotFoundException e) {
109            Log.e(TAG, "Can't get ServiceInfo for " + component.toShortString());
110        }
111    }
112
113    /**
114     * Called when the user attempted to authenticate on the device.
115     *
116     * @param successful true if the attempt succeeded
117     */
118    public void onUnlockAttempt(boolean successful) {
119    }
120
121    private void onError(String msg) {
122        Slog.v(TAG, "Remote exception while " + msg);
123    }
124
125    /**
126     * Call to grant trust on the device.
127     *
128     * @param message describes why the device is trusted, e.g. "Trusted by location".
129     * @param durationMs amount of time in milliseconds to keep the device in a trusted state. Trust
130     *                   for this agent will automatically be revoked when the timeout expires.
131     * @param initiatedByUser indicates that the user has explicitly initiated an action that proves
132     *                        the user is about to use the device.
133     */
134    public final void grantTrust(CharSequence message, long durationMs, boolean initiatedByUser) {
135        if (mCallback != null) {
136            try {
137                mCallback.grantTrust(message.toString(), durationMs, initiatedByUser);
138            } catch (RemoteException e) {
139                onError("calling enableTrust()");
140            }
141        }
142    }
143
144    /**
145     * Call to revoke trust on the device.
146     */
147    public final void revokeTrust() {
148        if (mCallback != null) {
149            try {
150                mCallback.revokeTrust();
151            } catch (RemoteException e) {
152                onError("calling revokeTrust()");
153            }
154        }
155    }
156
157    @Override
158    public final IBinder onBind(Intent intent) {
159        if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
160        return new TrustAgentServiceWrapper();
161    }
162
163    private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub {
164        @Override
165        public void onUnlockAttempt(boolean successful) {
166            mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0)
167                    .sendToTarget();
168        }
169
170        public void setCallback(ITrustAgentServiceCallback callback) {
171            mCallback = callback;
172        }
173    }
174
175}
176