1 /* 2 * Copyright (C) 2017 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 package com.android.car.trust; 17 18 import android.Manifest; 19 import android.app.Activity; 20 import android.bluetooth.BluetoothDevice; 21 import android.car.trust.ICarTrustAgentBleCallback; 22 import android.car.trust.ICarTrustAgentBleService; 23 import android.car.trust.ICarTrustAgentEnrolmentCallback; 24 import android.car.trust.ICarTrustAgentTokenResponseCallback; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.ServiceConnection; 29 import android.content.SharedPreferences; 30 import android.content.pm.PackageManager; 31 import android.os.Bundle; 32 import android.os.IBinder; 33 import android.os.RemoteException; 34 import android.os.UserHandle; 35 import android.preference.PreferenceManager; 36 import android.util.Log; 37 import android.widget.TextView; 38 39 /** 40 * Setup activity that binds {@link CarTrustAgentBleService} and starts the enrolment process. 41 */ 42 public class CarEnrolmentActivity extends Activity { 43 44 private static final String TAG = CarEnrolmentActivity.class.getSimpleName(); 45 46 private static final String SP_HANDLE_KEY = "sp-test"; 47 private static final int FINE_LOCATION_REQUEST_CODE = 42; 48 49 private final ICarTrustAgentTokenResponseCallback mCarTrustAgentTokenResponseCallback = 50 new ICarTrustAgentTokenResponseCallback.Stub() { 51 @Override 52 public void onEscrowTokenAdded(byte[] token, long handle, int uid) { 53 runOnUiThread(() -> { 54 mPrefs.edit().putLong(SP_HANDLE_KEY, handle).apply(); 55 Log.d(TAG, "stored new handle"); 56 }); 57 58 if (mBluetoothDevice == null) { 59 Log.e(TAG, "No active bluetooth found to add escrow token"); 60 return; 61 } 62 63 try { 64 // Notify the enrolment client that escrow token has been added 65 mCarTrustAgentBleService.sendEnrolmentHandle(mBluetoothDevice, handle); 66 appendOutputText("Escrow Token Added. Handle: " + handle); 67 appendOutputText("Lock and unlock the device to activate token"); 68 } catch (RemoteException e) { 69 Log.e(TAG, "Error sendEnrolmentHandle", e); 70 } 71 } 72 73 @Override 74 public void onEscrowTokenRemoved(long handle, boolean successful) { 75 appendOutputText("Escrow token Removed. Handle: " + handle); 76 } 77 78 @Override 79 public void onEscrowTokenActiveStateChanged(long handle, boolean active) { 80 appendOutputText("Is token active? " + active + " handle: " + handle); 81 } 82 }; 83 84 private final ICarTrustAgentBleCallback mBleConnectionCallback = 85 new ICarTrustAgentBleCallback.Stub() { 86 @Override 87 public void onBleServerStartSuccess() { 88 appendOutputText("Server started"); 89 } 90 91 @Override 92 public void onBleServerStartFailure(int errorCode) { 93 appendOutputText("Server failed to start, error code: " + errorCode); 94 } 95 96 @Override 97 public void onBleDeviceConnected(BluetoothDevice device) { 98 mBluetoothDevice = device; 99 appendOutputText("Device connected: " + device.getName() 100 + " address: " + device.getAddress()); 101 } 102 103 @Override 104 public void onBleDeviceDisconnected(BluetoothDevice device) { 105 mBluetoothDevice = null; 106 appendOutputText("Device disconnected: " + device.getName() 107 + " address: " + device.getAddress()); 108 } 109 }; 110 111 private final ICarTrustAgentEnrolmentCallback mEnrolmentCallback = 112 new ICarTrustAgentEnrolmentCallback.Stub() { 113 @Override 114 public void onEnrolmentDataReceived(byte[] token) { 115 appendOutputText("Enrolment data received "); 116 try { 117 addEscrowToken(token); 118 } catch (RemoteException e) { 119 Log.e(TAG, "Error addEscrowToken", e); 120 } 121 } 122 }; 123 124 private final ServiceConnection mServiceConnection = new ServiceConnection() { 125 @Override 126 public void onServiceConnected(ComponentName name, IBinder service) { 127 mCarTrustAgentBleServiceBound = true; 128 mCarTrustAgentBleService = ICarTrustAgentBleService.Stub.asInterface(service); 129 try { 130 mCarTrustAgentBleService.registerBleCallback(mBleConnectionCallback); 131 mCarTrustAgentBleService.registerEnrolmentCallback(mEnrolmentCallback); 132 mCarTrustAgentBleService.setTokenResponseCallback( 133 mCarTrustAgentTokenResponseCallback); 134 mCarTrustAgentBleService.startEnrolmentAdvertising(); 135 } catch (RemoteException e) { 136 Log.e(TAG, "Error startEnrolmentAdvertising", e); 137 } 138 } 139 140 @Override 141 public void onServiceDisconnected(ComponentName name) { 142 if (mCarTrustAgentBleService != null) { 143 try { 144 mCarTrustAgentBleService.unregisterBleCallback(mBleConnectionCallback); 145 mCarTrustAgentBleService.unregisterEnrolmentCallback(mEnrolmentCallback); 146 mCarTrustAgentBleService.setTokenResponseCallback(null); 147 mCarTrustAgentBleService.stopEnrolmentAdvertising(); 148 } catch (RemoteException e) { 149 Log.e(TAG, "Error unregister callbacks", e); 150 } 151 mCarTrustAgentBleService = null; 152 } 153 mCarTrustAgentBleServiceBound = false; 154 } 155 }; 156 157 private TextView mOutputText; 158 private BluetoothDevice mBluetoothDevice; 159 private ICarTrustAgentBleService mCarTrustAgentBleService; 160 private boolean mCarTrustAgentBleServiceBound; 161 private SharedPreferences mPrefs; 162 163 @Override 164 protected void onCreate(Bundle savedInstanceState) { 165 super.onCreate(savedInstanceState); 166 167 setContentView(R.layout.car_enrolment_activity); 168 mOutputText = findViewById(R.id.textfield); 169 mPrefs = PreferenceManager.getDefaultSharedPreferences(this /* context */); 170 171 findViewById(R.id.start_button).setOnClickListener((view) -> { 172 Intent bindIntent = new Intent(this, CarTrustAgentBleService.class); 173 bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE); 174 }); 175 176 findViewById(R.id.revoke_trust_button).setOnClickListener((view) -> { 177 if (mCarTrustAgentBleServiceBound) { 178 try { 179 mCarTrustAgentBleService.revokeTrust(); 180 } catch (RemoteException e) { 181 Log.e(TAG, "Error revokeTrust", e); 182 } 183 } 184 }); 185 } 186 187 @Override 188 protected void onResume() { 189 super.onResume(); 190 191 if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != 192 PackageManager.PERMISSION_GRANTED) { 193 requestPermissions( 194 new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION }, 195 FINE_LOCATION_REQUEST_CODE); 196 } else { 197 long tokenHandle = getTokenHandle(); 198 if (tokenHandle != -1) { 199 Log.d(TAG, "onResume, checking handle active: " + tokenHandle); 200 if (mCarTrustAgentBleServiceBound) { 201 try { 202 // Due to the asynchronous nature of isEscrowTokenActive in 203 // TrustAgentService, query result will be delivered via 204 // {@link #mCarTrustAgentTokenResponseCallback} 205 mCarTrustAgentBleService.isEscrowTokenActive(tokenHandle, 206 UserHandle.myUserId()); 207 } catch (RemoteException e) { 208 Log.e(TAG, "Error isEscrowTokenActive", e); 209 } 210 } 211 } else { 212 appendOutputText("No handles found"); 213 } 214 } 215 } 216 217 @Override 218 protected void onDestroy() { 219 if (mCarTrustAgentBleServiceBound) { 220 unbindService(mServiceConnection); 221 } 222 super.onDestroy(); 223 } 224 225 private void appendOutputText(final String text) { 226 runOnUiThread(() -> mOutputText.append("\n" + text)); 227 } 228 229 private void addEscrowToken(byte[] token) throws RemoteException { 230 if (!mCarTrustAgentBleServiceBound) { 231 Log.e(TAG, "No CarTrustAgentBleService bounded"); 232 return; 233 } 234 mCarTrustAgentBleService.addEscrowToken(token, UserHandle.myUserId()); 235 } 236 237 private long getTokenHandle() { 238 return mPrefs.getLong(SP_HANDLE_KEY, -1); 239 } 240 } 241