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