aboutsummaryrefslogtreecommitdiff
path: root/TrustAgent/src
diff options
context:
space:
mode:
authorHongwei Wang <hwwang@google.com>2018-04-12 12:24:08 -0700
committerHongwei Wang <hwwang@google.com>2018-04-17 13:29:03 -0700
commit779f513f6a40a9ae041fc64d5f55a98b1ffe558b (patch)
treec860f6ba1222ecb71dcf817d84ea8c5e89f203c3 /TrustAgent/src
parentd380b9461a9bc1dac949ee0b52e02746c3b0e164 (diff)
downloadCar-779f513f6a40a9ae041fc64d5f55a98b1ffe558b.tar.gz
Merges CarEnrolmentService and CarUnlockService
This is a major overhaul of car TrustAgent component for I/O 2018 trust device demo Highlights: - Reduces the number of services from 3 to 2. Would like to be one but CarBleTrustAgent[TrustAgent] declares its onBind method as final - CarEnrolmentActivity lives as a reference how to communicate with CarTrustAgentBleService and maybe removed from the final release - Both CarBleTrustAgent[TrustAgent] and CarEnrolmentActivity talk to the CarTrustAgentBleService for token exchanging What's next: - Simplify the reference CarEnrolmentActivity, it currently holds implementations should live in underlying service Bug: 76008345 Test: manual Change-Id: I54090db88c1f701b1e79f623ac0c415be55f59b9
Diffstat (limited to 'TrustAgent/src')
-rw-r--r--TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java179
-rw-r--r--TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java124
-rw-r--r--TrustAgent/src/com/android/car/trust/CarEnrolmentService.java141
-rw-r--r--TrustAgent/src/com/android/car/trust/CarTrustAgentBleService.java308
-rw-r--r--TrustAgent/src/com/android/car/trust/CarUnlockService.java149
-rw-r--r--TrustAgent/src/com/android/car/trust/SimpleBleServer.java138
-rw-r--r--TrustAgent/src/com/android/car/trust/Utils.java36
7 files changed, 531 insertions, 544 deletions
diff --git a/TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java b/TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java
index 352f978abb..2c46dea6a4 100644
--- a/TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java
+++ b/TrustAgent/src/com/android/car/trust/CarBleTrustAgent.java
@@ -20,6 +20,8 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothManager;
+import android.car.trust.ICarTrustAgentBleService;
+import android.car.trust.ICarTrustAgentUnlockCallback;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -28,6 +30,7 @@ import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.trust.TrustAgentService;
@@ -38,7 +41,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.util.concurrent.TimeUnit;
/**
- * A sample trust agent that demonstrates how to use the escrow token unlock APIs. </p>
+ * A BluetoothLE (BLE) based {@link TrustAgentService} that uses the escrow token unlock APIs. </p>
*
* This trust agent runs during direct boot and binds to a BLE service that listens for remote
* devices to trigger an unlock. <p/>
@@ -46,11 +49,13 @@ import java.util.concurrent.TimeUnit;
* The permissions for this agent must be enabled as priv-app permissions for it to start.
*/
public class CarBleTrustAgent extends TrustAgentService {
+
+ private static final String TAG = CarBleTrustAgent.class.getSimpleName();
+
public static final String ACTION_REVOKE_TRUST = "revoke-trust-action";
public static final String ACTION_ADD_TOKEN = "add-token-action";
public static final String ACTION_IS_TOKEN_ACTIVE = "is-token-active-action";
public static final String ACTION_REMOVE_TOKEN = "remove-token-action";
- public static final String ACTION_UNLOCK_DEVICE = "unlock-device-action";
public static final String ACTION_TOKEN_STATUS_RESULT = "token-status-result-action";
public static final String ACTION_ADD_TOKEN_RESULT = "add-token-result-action";
@@ -64,18 +69,17 @@ public class CarBleTrustAgent extends TrustAgentService {
private Handler mHandler;
private BluetoothManager mBluetoothManager;
- private CarUnlockService mCarUnlockService;
+ private ICarTrustAgentBleService mCarTrustAgentBleService;
+ private boolean mCarTrustAgentBleServiceBound;
private LocalBroadcastManager mLocalBroadcastManager;
- private boolean mBleServiceBound;
-
// We cannot directly bind to TrustAgentService since the onBind method is final.
// As a result, we communicate with the various UI components using a LocalBroadcastManager.
private final BroadcastReceiver mTrustEventReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- Log.d(Utils.LOG_TAG, "Received broadcast: " + action);
+ Log.d(TAG, "Received broadcast: " + action);
if (ACTION_REVOKE_TRUST.equals(action)) {
revokeTrust();
} else if (ACTION_ADD_TOKEN.equals(action)) {
@@ -91,60 +95,70 @@ public class CarBleTrustAgent extends TrustAgentService {
}
};
- private final SimpleBleServer.ConnectionCallback mConnectionCallback
- = new SimpleBleServer.ConnectionCallback() {
+ private final ICarTrustAgentUnlockCallback mUnlockCallback =
+ new ICarTrustAgentUnlockCallback.Stub() {
@Override
- public void onServerStarted() {
- Log.d(Utils.LOG_TAG, "BLE server started");
- }
-
- @Override
- public void onServerStartFailed(int errorCode) {
- Log.e(Utils.LOG_TAG, "BLE server failed to start. Error Code: " + errorCode);
- }
+ public void onUnlockDataReceived(byte[] token, long handle) {
+ UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
+ // TODO(b/77854782): get the actual user to unlock by token
+ UserHandle userHandle = getForegroundUserHandle();
+
+ Log.d(TAG, "About to unlock user. Handle: " + handle
+ + " Time: " + System.currentTimeMillis());
+ unlockUserWithToken(handle, token, userHandle);
+
+ Log.d(TAG, "Attempted to unlock user, is user unlocked: "
+ + um.isUserUnlocked(userHandle)
+ + " Time: " + System.currentTimeMillis());
+ setManagingTrust(true);
- @Override
- public void onDeviceConnected(BluetoothDevice device) {
- Log.d(Utils.LOG_TAG, "BLE device connected. Name: " + device.getName()
- + " Address: " + device.getAddress());
+ if (um.isUserUnlocked(userHandle)) {
+ Log.d(TAG, getString(R.string.trust_granted_explanation));
+ grantTrust("Granting trust from escrow token",
+ TRUST_DURATION_MS, FLAG_GRANT_TRUST_DISMISS_KEYGUARD);
+ // Trust has been granted, disable the BLE server. This trust agent service does
+ // not need to receive additional BLE data.
+ unbindService(mServiceConnection);
+ }
}
};
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- Log.d(Utils.LOG_TAG, "CarUnlockService connected");
- mBleServiceBound = true;
- CarUnlockService.UnlockServiceBinder binder
- = (CarUnlockService.UnlockServiceBinder) service;
- mCarUnlockService = binder.getService();
- mCarUnlockService.setOnUnlockDeviceListener(CarBleTrustAgent.this::unlock);
- mCarUnlockService.registerConnectionCallback(mConnectionCallback);
- maybeStartBleUnlockService();
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.d(TAG, "CarTrustAgentBleService connected");
+ mCarTrustAgentBleServiceBound = true;
+ mCarTrustAgentBleService = ICarTrustAgentBleService.Stub.asInterface(service);
+ try {
+ mCarTrustAgentBleService.registerUnlockCallback(mUnlockCallback);
+ maybeStartBleUnlockService();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error registerUnlockCallback", e);
+ }
}
@Override
- public void onServiceDisconnected(ComponentName arg0) {
- mCarUnlockService = null;
- mBleServiceBound = false;
+ public void onServiceDisconnected(ComponentName name) {
+ if (mCarTrustAgentBleService != null) {
+ try {
+ mCarTrustAgentBleService.unregisterUnlockCallback(mUnlockCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error unregisterUnlockCallback", e);
+ }
+ mCarTrustAgentBleService = null;
+ mCarTrustAgentBleServiceBound = false;
+ }
}
-
};
@Override
- public void onTrustTimeout() {
- super.onTrustTimeout();
- Log.d(Utils.LOG_TAG, "onTrustTimeout(): timeout expired");
- }
-
- @Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
- Log.d(Utils.LOG_TAG, "Bluetooth trust agent starting up");
+ Log.d(TAG, "Bluetooth trust agent starting up");
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_REVOKE_TRUST);
filter.addAction(ACTION_ADD_TOKEN);
@@ -157,9 +171,8 @@ public class CarBleTrustAgent extends TrustAgentService {
// If the user is already unlocked, don't bother starting the BLE service.
UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
if (!um.isUserUnlocked(getForegroundUserHandle())) {
- Log.d(Utils.LOG_TAG, "User locked, will now bind CarUnlockService");
- Intent intent = new Intent(this, CarUnlockService.class);
-
+ Log.d(TAG, "User locked, will now bind CarTrustAgentBleService");
+ Intent intent = new Intent(this, CarTrustAgentBleService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
} else {
setManagingTrust(true);
@@ -168,19 +181,45 @@ public class CarBleTrustAgent extends TrustAgentService {
@Override
public void onDestroy() {
- Log.d(Utils.LOG_TAG, "Car Trust agent shutting down");
+ Log.d(TAG, "Car Trust agent shutting down");
mHandler.removeCallbacks(null);
mLocalBroadcastManager.unregisterReceiver(mTrustEventReceiver);
// Unbind the service to avoid leaks from BLE stack.
- if (mBleServiceBound) {
+ if (mCarTrustAgentBleServiceBound) {
unbindService(mServiceConnection);
}
super.onDestroy();
}
+ @Override
+ public void onDeviceLocked() {
+ super.onDeviceLocked();
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ // Only one BLE advertising is allowed, ensure enrolment advertising is stopped.
+ mCarTrustAgentBleService.stopEnrolmentAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error stopEnrolmentAdvertising", e);
+ }
+ }
+ }
+
+ @Override
+ public void onDeviceUnlocked() {
+ super.onDeviceUnlocked();
+ if (mCarTrustAgentBleServiceBound) {
+ try {
+ // Only one BLE advertising is allowed, ensure unlock advertising is stopped.
+ mCarTrustAgentBleService.stopUnlockAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error stopUnlockAdvertising", e);
+ }
+ }
+ }
+
private void maybeStartBleUnlockService() {
- Log.d(Utils.LOG_TAG, "Trying to open a Ble GATT server");
+ Log.d(TAG, "Trying to open a Ble GATT server");
BluetoothGattServer gattServer = mBluetoothManager.openGattServer(
this, new BluetoothGattServerCallback() {
@Override
@@ -193,49 +232,29 @@ public class CarBleTrustAgent extends TrustAgentService {
// might not be ready just yet. Keep trying until a GattServer can open up before proceeding
// to start the rest of the BLE services.
if (gattServer == null) {
- Log.e(Utils.LOG_TAG, "Gatt not available, will try again...in " + BLE_RETRY_MS + "ms");
- mHandler.postDelayed(() -> maybeStartBleUnlockService(), BLE_RETRY_MS);
+ Log.e(TAG, "Gatt not available, will try again...in " + BLE_RETRY_MS + "ms");
+ mHandler.postDelayed(this::maybeStartBleUnlockService, BLE_RETRY_MS);
} else {
mHandler.removeCallbacks(null);
gattServer.close();
- Log.d(Utils.LOG_TAG, "GATT available, starting up UnlockService");
- mCarUnlockService.start();
- }
- }
-
- private void unlock(byte[] token, long handle) {
- UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
- // STOPSHIP: get the actual user to unlock by token
- UserHandle userHandle = getForegroundUserHandle();
-
- Log.d(Utils.LOG_TAG, "About to unlock user. Handle: " + handle
- + " Time: " + System.currentTimeMillis());
- unlockUserWithToken(handle, token, userHandle);
-
- Log.d(Utils.LOG_TAG, "Attempted to unlock user, is user unlocked: "
- + um.isUserUnlocked(userHandle)
- + " Time: " + System.currentTimeMillis());
- setManagingTrust(true);
-
- if (um.isUserUnlocked(userHandle)) {
- Log.d(Utils.LOG_TAG, getString(R.string.trust_granted_explanation));
- grantTrust("Granting trust from escrow token",
- TRUST_DURATION_MS, FLAG_GRANT_TRUST_DISMISS_KEYGUARD);
- // Trust has been granted, disable the BLE server. This trust agent service does
- // not need to receive additional BLE data.
- unbindService(mServiceConnection);
+ Log.d(TAG, "GATT available, starting up UnlockService");
+ try {
+ mCarTrustAgentBleService.startUnlockAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error startUnlockAdvertising", e);
+ }
}
}
@Override
public void onEscrowTokenRemoved(long handle, boolean successful) {
- Log.d(Utils.LOG_TAG, "onEscrowTokenRemoved. Handle: " + handle + " successful? " + successful);
+ Log.d(TAG, "onEscrowTokenRemoved. Handle: " + handle + " successful? " + successful);
}
@Override
public void onEscrowTokenStateReceived(long handle, int tokenState) {
boolean isActive = tokenState == TOKEN_STATE_ACTIVE;
- Log.d(Utils.LOG_TAG, "Token handle: " + handle + " isActive: " + isActive);
+ Log.d(TAG, "Token handle: " + handle + " isActive: " + isActive);
Intent intent = new Intent();
intent.setAction(ACTION_TOKEN_STATUS_RESULT);
@@ -246,7 +265,7 @@ public class CarBleTrustAgent extends TrustAgentService {
@Override
public void onEscrowTokenAdded(byte[] token, long handle, UserHandle user) {
- Log.d(Utils.LOG_TAG, "onEscrowTokenAdded, handle: " + handle);
+ Log.d(TAG, "onEscrowTokenAdded, handle: " + handle);
Intent intent = new Intent();
intent.setAction(ACTION_ADD_TOKEN_RESULT);
intent.putExtra(INTENT_EXTRA_TOKEN_HANDLE, handle);
@@ -255,11 +274,11 @@ public class CarBleTrustAgent extends TrustAgentService {
}
/**
- * STOPSHIP: return the {@link UserHandle} of foreground user.
- * CarTrustAgentService itself runs as user-0
+ * TODO(b/77854782): return the {@link UserHandle} of foreground user.
+ * CarBleTrustAgent itself runs as user-0
*/
private UserHandle getForegroundUserHandle() {
- Log.d(Utils.LOG_TAG, "getForegroundUserHandle for " + UserHandle.myUserId());
+ Log.d(TAG, "getForegroundUserHandle for " + UserHandle.myUserId());
return UserHandle.of(UserHandle.myUserId());
}
}
diff --git a/TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java b/TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java
index 8047a4b447..2723a6a34a 100644
--- a/TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java
+++ b/TrustAgent/src/com/android/car/trust/CarEnrolmentActivity.java
@@ -23,6 +23,9 @@ import static com.android.car.trust.CarBleTrustAgent.INTENT_EXTRA_TOKEN_STATUS;
import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
+import android.car.trust.ICarTrustAgentBleCallback;
+import android.car.trust.ICarTrustAgentBleService;
+import android.car.trust.ICarTrustAgentEnrolmentCallback;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -40,13 +43,13 @@ import android.widget.TextView;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
-import com.android.car.trust.CarEnrolmentService.OnEnrolmentDataReceivedListener;
-import com.android.car.trust.SimpleBleServer.ConnectionCallback;
-
/**
- * Setup activity that binds {@link CarEnrolmentService} and starts the enrolment process.
+ * Setup activity that binds {@link CarTrustAgentBleService} and starts the enrolment process.
*/
public class CarEnrolmentActivity extends Activity {
+
+ private static final String TAG = CarEnrolmentActivity.class.getSimpleName();
+
private static final String SP_HANDLE_KEY = "sp-test";
private static final int FINE_LOCATION_REQUEST_CODE = 42;
@@ -54,77 +57,100 @@ public class CarEnrolmentActivity extends Activity {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- Log.d(Utils.LOG_TAG, "Received broadcast: " + action);
+ Log.d(TAG, "Received broadcast: " + action);
if (ACTION_TOKEN_STATUS_RESULT.equals(action)) {
boolean tokenActive = intent.getBooleanExtra(INTENT_EXTRA_TOKEN_STATUS, false);
- appendOutputText("Is token active? " + tokenActive + " handle: " + mHandle);
+ appendOutputText("Is token active? " + tokenActive + " handle: " + mTokenHandle);
} else if (ACTION_ADD_TOKEN_RESULT.equals(action)) {
final long handle = intent.getLongExtra(INTENT_EXTRA_TOKEN_HANDLE, -1);
runOnUiThread(() -> {
mPrefs.edit().putLong(SP_HANDLE_KEY, handle).apply();
- Log.d(Utils.LOG_TAG, "stored new handle");
+ Log.d(TAG, "stored new handle");
});
- mEnrolmentService.sendHandle(handle, mDevice);
- appendOutputText("Escrow Token Added. Handle: " + handle
- + "\nLock and unlock the device to activate token");
+ try {
+ mCarTrustAgentBleService.sendEnrolmentHandle(mDevice, handle);
+ appendOutputText("Escrow Token Added. Handle: " + handle
+ + "\nLock and unlock the device to activate token");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error sendEnrolmentHandle", e);
+ }
}
}
};
- private final ConnectionCallback mConnectionCallback = new ConnectionCallback() {
+ private final ICarTrustAgentBleCallback mBleConnectionCallback =
+ new ICarTrustAgentBleCallback.Stub() {
@Override
- public void onServerStarted() {
+ public void onBleServerStartSuccess() {
appendOutputText("Server started");
}
@Override
- public void onServerStartFailed(int errorCode) {
+ public void onBleServerStartFailure(int errorCode) {
appendOutputText("Server failed to start, error code: " + errorCode);
}
@Override
- public void onDeviceConnected(BluetoothDevice device) {
+ public void onBleDeviceConnected(BluetoothDevice device) {
mDevice = device;
appendOutputText("Device connected: " + device.getName()
- + " addr: " + device.getAddress());
+ + " address: " + device.getAddress());
+ }
+
+ @Override
+ public void onBleDeviceDisconnected(BluetoothDevice device) {
+ mDevice = null;
+ appendOutputText("Device disconnected: " + device.getName()
+ + " address: " + device.getAddress());
}
};
- private final OnEnrolmentDataReceivedListener mEnrolmentListener = (byte[] token) -> {
- appendOutputText("Enrolment data received ");
- addEscrowToken(token);
+ private final ICarTrustAgentEnrolmentCallback mEnrolmentCallback =
+ new ICarTrustAgentEnrolmentCallback.Stub() {
+ @Override
+ public void onEnrolmentDataReceived(byte[] token) {
+ appendOutputText("Enrolment data received ");
+ addEscrowToken(token);
+ }
};
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
- public void onServiceConnected(ComponentName className,
- IBinder service) {
- mServiceBound = true;
- CarEnrolmentService.EnrolmentServiceBinder binder
- = (CarEnrolmentService.EnrolmentServiceBinder) service;
- mEnrolmentService = binder.getService();
- mEnrolmentService.registerEnrolmentListener(mEnrolmentListener);
- mEnrolmentService.registerConnectionCallback(mConnectionCallback);
- mEnrolmentService.start();
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mCarTrustAgentBleServiceBound = true;
+ mCarTrustAgentBleService = ICarTrustAgentBleService.Stub.asInterface(service);
+ try {
+ mCarTrustAgentBleService.registerBleCallback(mBleConnectionCallback);
+ mCarTrustAgentBleService.registerEnrolmentCallback(mEnrolmentCallback);
+ mCarTrustAgentBleService.startEnrolmentAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error startEnrolmentAdvertising", e);
+ }
}
@Override
- public void onServiceDisconnected(ComponentName arg0) {
- mEnrolmentService.unregisterEnrolmentListener(mEnrolmentListener);
- mEnrolmentService.unregisterConnectionCallback(mConnectionCallback);
- mEnrolmentService = null;
- mServiceBound = false;
+ public void onServiceDisconnected(ComponentName name) {
+ if (mCarTrustAgentBleService != null) {
+ try {
+ mCarTrustAgentBleService.unregisterBleCallback(mBleConnectionCallback);
+ mCarTrustAgentBleService.unregisterEnrolmentCallback(mEnrolmentCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error unregister callbacks", e);
+ }
+ mCarTrustAgentBleService = null;
+ }
+ mCarTrustAgentBleServiceBound = false;
}
};
private TextView mOutputText;
- private long mHandle;
- private CarEnrolmentService mEnrolmentService;
+ private long mTokenHandle;
+ private ICarTrustAgentBleService mCarTrustAgentBleService;
+ private boolean mCarTrustAgentBleServiceBound;
private BluetoothDevice mDevice;
- private boolean mServiceBound;
private LocalBroadcastManager mLocalBroadcastManager;
private SharedPreferences mPrefs;
@@ -144,7 +170,7 @@ public class CarEnrolmentActivity extends Activity {
mLocalBroadcastManager.registerReceiver(mReceiver, filter);
findViewById(R.id.start_button).setOnClickListener((view) -> {
- Intent bindIntent = new Intent(this, CarEnrolmentService.class);
+ Intent bindIntent = new Intent(this, CarTrustAgentBleService.class);
bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
});
@@ -164,26 +190,20 @@ public class CarEnrolmentActivity extends Activity {
requestPermissions(
new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION },
FINE_LOCATION_REQUEST_CODE);
- }
-
- if (!mPrefs.contains(SP_HANDLE_KEY)) {
- appendOutputText("No handles found.");
- return;
- }
-
- try {
- mHandle = mPrefs.getLong(SP_HANDLE_KEY, -1);
- Log.d(Utils.LOG_TAG, "onResume, checking handle active: " + mHandle);
- isTokenActive(mHandle);
- } catch (RemoteException e) {
- Log.e(Utils.LOG_TAG, "Error checking if token is valid");
- appendOutputText("Error checking if token is valid");
+ } else {
+ if (mPrefs.contains(SP_HANDLE_KEY)) {
+ mTokenHandle = mPrefs.getLong(SP_HANDLE_KEY, -1);
+ Log.d(TAG, "onResume, checking handle active: " + mTokenHandle);
+ isTokenActive(mTokenHandle);
+ } else {
+ appendOutputText("No handles found");
+ }
}
}
@Override
protected void onDestroy() {
- if (mServiceBound) {
+ if (mCarTrustAgentBleServiceBound) {
unbindService(mServiceConnection);
}
super.onDestroy();
@@ -193,7 +213,7 @@ public class CarEnrolmentActivity extends Activity {
runOnUiThread(() -> mOutputText.append("\n" + text));
}
- private void isTokenActive(long handle) throws RemoteException {
+ private void isTokenActive(long handle) {
Intent intent = new Intent();
intent.setAction(CarBleTrustAgent.ACTION_IS_TOKEN_ACTIVE);
intent.putExtra(CarBleTrustAgent.INTENT_EXTRA_TOKEN_HANDLE, handle);
diff --git a/TrustAgent/src/com/android/car/trust/CarEnrolmentService.java b/TrustAgent/src/com/android/car/trust/CarEnrolmentService.java
deleted file mode 100644
index 16b6bdfbe7..0000000000
--- a/TrustAgent/src/com/android/car/trust/CarEnrolmentService.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.car.trust;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.util.Log;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * A service that receives escrow token enrollment requests from remote devices.
- */
-public class CarEnrolmentService extends SimpleBleServer {
-
- private final Set<OnEnrolmentDataReceivedListener> mEnrolmentListeners = new HashSet<>();
- private final IBinder mBinder = new EnrolmentServiceBinder();
-
- private BluetoothGattService mEnrolmentService;
- private BluetoothGattCharacteristic mEnrolmentEscrowToken;
- private BluetoothGattCharacteristic mEnrolmentTokenHandle;
-
- @Override
- public void onCreate() {
- super.onCreate();
- setupEnrolmentService();
- }
-
- public void start() {
- ParcelUuid uuid = new ParcelUuid(
- UUID.fromString(getString(R.string.enrollment_service_uuid)));
- Log.d(Utils.LOG_TAG, "CarEnrolmentService start with uuid: " + uuid);
- start(uuid, mEnrolmentService, new Handler());
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- @Override
- public void onCharacteristicWrite(BluetoothDevice device,
- int requestId, BluetoothGattCharacteristic characteristic,
- boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
- if (characteristic.getUuid().equals(mEnrolmentEscrowToken.getUuid())) {
- Log.d(Utils.LOG_TAG, "Enrolment token received, value: " + Utils.getLong(value));
- for (OnEnrolmentDataReceivedListener callback : mEnrolmentListeners) {
- callback.onEnrolmentDataReceived(value);
- }
- }
- }
-
- @Override
- public void onCharacteristicRead(BluetoothDevice device,
- int requestId, int offset, BluetoothGattCharacteristic characteristic) {
- //Enrolment service should not have any read requests.
- }
-
- /**
- * Register {@link OnEnrolmentDataReceivedListener} to receive the enrolment data
- * @param listener
- */
- public void registerEnrolmentListener(OnEnrolmentDataReceivedListener listener) {
- mEnrolmentListeners.add(listener);
- }
-
- /**
- * Unregister {@link OnEnrolmentDataReceivedListener} from receiving enrolment data
- * @param listener
- */
- public void unregisterEnrolmentListener(OnEnrolmentDataReceivedListener listener) {
- mEnrolmentListeners.remove(listener);
- }
-
- public void sendHandle(long handle, BluetoothDevice device) {
- mEnrolmentTokenHandle.setValue(Utils.getBytes(handle));
-
- Log.d(Utils.LOG_TAG, "Sending notification for EscrowToken Handle");
- notifyCharacteristicChanged(device, mEnrolmentTokenHandle, false);
- }
-
- public class EnrolmentServiceBinder extends Binder {
- public CarEnrolmentService getService() {
- return CarEnrolmentService.this;
- }
- }
-
- // Create services and characteristics for enrolling new unlocking escrow tokens
- private void setupEnrolmentService() {
- mEnrolmentService = new BluetoothGattService(
- UUID.fromString(getString(R.string.enrollment_service_uuid)),
- BluetoothGattService.SERVICE_TYPE_PRIMARY);
-
- // Characteristic to describe the escrow token being used for unlock
- mEnrolmentEscrowToken = new BluetoothGattCharacteristic(
- UUID.fromString(getString(R.string.enrollment_token_uuid)),
- BluetoothGattCharacteristic.PROPERTY_WRITE,
- BluetoothGattCharacteristic.PERMISSION_WRITE);
-
- // Characteristic to describe the handle being used for this escrow token
- mEnrolmentTokenHandle = new BluetoothGattCharacteristic(
- UUID.fromString(getString(R.string.enrollment_handle_uuid)),
- BluetoothGattCharacteristic.PROPERTY_NOTIFY,
- BluetoothGattCharacteristic.PERMISSION_READ);
-
- mEnrolmentService.addCharacteristic(mEnrolmentEscrowToken);
- mEnrolmentService.addCharacteristic(mEnrolmentTokenHandle);
- }
-
- /**
- * Interface to receive enrolment data.
- */
- public interface OnEnrolmentDataReceivedListener {
- /**
- * Called when the enrolment data is received
- * @param token enrolment data
- */
- void onEnrolmentDataReceived(byte[] token);
- }
-}
diff --git a/TrustAgent/src/com/android/car/trust/CarTrustAgentBleService.java b/TrustAgent/src/com/android/car/trust/CarTrustAgentBleService.java
new file mode 100644
index 0000000000..392bd7593b
--- /dev/null
+++ b/TrustAgent/src/com/android/car/trust/CarTrustAgentBleService.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.trust;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.car.trust.ICarTrustAgentBleCallback;
+import android.car.trust.ICarTrustAgentBleService;
+import android.car.trust.ICarTrustAgentEnrolmentCallback;
+import android.car.trust.ICarTrustAgentUnlockCallback;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.ParcelUuid;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+/**
+ * Abstracts enrolment and unlock token exchange via BluetoothLE (BLE).
+ * {@link CarBleTrustAgent} and any enrolment client should bind to
+ * {@link ICarTrustAgentBleService}.
+ */
+public class CarTrustAgentBleService extends SimpleBleServer {
+
+ private static final String TAG = CarTrustAgentBleService.class.getSimpleName();
+
+ private RemoteCallbackList<ICarTrustAgentBleCallback> mBleCallbacks;
+ private RemoteCallbackList<ICarTrustAgentEnrolmentCallback> mEnrolmentCallbacks;
+ private RemoteCallbackList<ICarTrustAgentUnlockCallback> mUnlockCallbacks;
+ private CarTrustAgentBleWrapper mCarTrustBleService;
+
+ private ParcelUuid mEnrolmentUuid;
+ private BluetoothGattCharacteristic mEnrolmentEscrowToken;
+ private BluetoothGattCharacteristic mEnrolmentTokenHandle;
+ private BluetoothGattService mEnrolmentGattServer;
+
+ private ParcelUuid mUnlockUuid;
+ private BluetoothGattCharacteristic mUnlockEscrowToken;
+ private BluetoothGattCharacteristic mUnlockTokenHandle;
+ private BluetoothGattService mUnlockGattServer;
+ private byte[] mCurrentUnlockToken;
+ private Long mCurrentUnlockHandle;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mBleCallbacks = new RemoteCallbackList<>();
+ mEnrolmentCallbacks = new RemoteCallbackList<>();
+ mUnlockCallbacks = new RemoteCallbackList<>();
+ mCarTrustBleService = new CarTrustAgentBleWrapper();
+
+ setupEnrolmentBleServer();
+ setupUnlockBleServer();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mCarTrustBleService;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ // keep it alive.
+ return START_STICKY;
+ }
+
+ @Override
+ public void onCharacteristicWrite(final BluetoothDevice device, int requestId,
+ BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
+ responseNeeded, int offset, byte[] value) {
+ UUID uuid = characteristic.getUuid();
+ Log.d(TAG, "onCharacteristicWrite received uuid: " + uuid);
+ if (uuid.equals(mEnrolmentEscrowToken.getUuid())) {
+ final int callbackCount = mEnrolmentCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mEnrolmentCallbacks.getBroadcastItem(i).onEnrolmentDataReceived(value);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onEnrolmentDataReceived", e);
+ }
+ }
+ mEnrolmentCallbacks.finishBroadcast();
+ } else if (uuid.equals(mUnlockEscrowToken.getUuid())) {
+ mCurrentUnlockToken = value;
+ maybeSendUnlockToken();
+ } else if (uuid.equals(mUnlockTokenHandle.getUuid())) {
+ mCurrentUnlockHandle = getLong(value);
+ maybeSendUnlockToken();
+ }
+ }
+
+ @Override
+ public void onCharacteristicRead(BluetoothDevice device,
+ int requestId, int offset, final BluetoothGattCharacteristic characteristic) {
+ // Ignored read requests.
+ }
+
+ @Override
+ protected void onAdvertiseStartSuccess() {
+ final int callbackCount = mBleCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mBleCallbacks.getBroadcastItem(i).onBleServerStartSuccess();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onBleServerStartSuccess", e);
+ }
+ }
+ mBleCallbacks.finishBroadcast();
+ }
+
+ @Override
+ protected void onAdvertiseStartFailure(int errorCode) {
+ final int callbackCount = mBleCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mBleCallbacks.getBroadcastItem(i).onBleServerStartFailure(errorCode);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onBleServerStartFailure", e);
+ }
+ }
+ mBleCallbacks.finishBroadcast();
+ }
+
+ @Override
+ protected void onAdvertiseDeviceConnected(BluetoothDevice device) {
+ final int callbackCount = mBleCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mBleCallbacks.getBroadcastItem(i).onBleDeviceConnected(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onBleDeviceConnected", e);
+ }
+ }
+ mBleCallbacks.finishBroadcast();
+ }
+
+ @Override
+ protected void onAdvertiseDeviceDisconnected(BluetoothDevice device) {
+ final int callbackCount = mBleCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mBleCallbacks.getBroadcastItem(i).onBleDeviceDisconnected(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onBleDeviceDisconnected", e);
+ }
+ }
+ mBleCallbacks.finishBroadcast();
+ }
+
+ private void setupEnrolmentBleServer() {
+ mEnrolmentUuid = new ParcelUuid(
+ UUID.fromString(getString(R.string.enrollment_service_uuid)));
+ mEnrolmentGattServer = new BluetoothGattService(
+ UUID.fromString(getString(R.string.enrollment_service_uuid)),
+ BluetoothGattService.SERVICE_TYPE_PRIMARY);
+
+ // Characteristic to describe the escrow token being used for unlock
+ mEnrolmentEscrowToken = new BluetoothGattCharacteristic(
+ UUID.fromString(getString(R.string.enrollment_token_uuid)),
+ BluetoothGattCharacteristic.PROPERTY_WRITE,
+ BluetoothGattCharacteristic.PERMISSION_WRITE);
+
+ // Characteristic to describe the handle being used for this escrow token
+ mEnrolmentTokenHandle = new BluetoothGattCharacteristic(
+ UUID.fromString(getString(R.string.enrollment_handle_uuid)),
+ BluetoothGattCharacteristic.PROPERTY_NOTIFY,
+ BluetoothGattCharacteristic.PERMISSION_READ);
+
+ mEnrolmentGattServer.addCharacteristic(mEnrolmentEscrowToken);
+ mEnrolmentGattServer.addCharacteristic(mEnrolmentTokenHandle);
+ }
+
+ private void setupUnlockBleServer() {
+ mUnlockUuid = new ParcelUuid(
+ UUID.fromString(getString(R.string.unlock_service_uuid)));
+ mUnlockGattServer = new BluetoothGattService(
+ UUID.fromString(getString(R.string.unlock_service_uuid)),
+ BluetoothGattService.SERVICE_TYPE_PRIMARY);
+
+ // Characteristic to describe the escrow token being used for unlock
+ mUnlockEscrowToken = new BluetoothGattCharacteristic(
+ UUID.fromString(getString(R.string.unlock_escrow_token_uiid)),
+ BluetoothGattCharacteristic.PROPERTY_WRITE,
+ BluetoothGattCharacteristic.PERMISSION_WRITE);
+
+ // Characteristic to describe the handle being used for this escrow token
+ mUnlockTokenHandle = new BluetoothGattCharacteristic(
+ UUID.fromString(getString(R.string.unlock_handle_uiid)),
+ BluetoothGattCharacteristic.PROPERTY_WRITE,
+ BluetoothGattCharacteristic.PERMISSION_WRITE);
+
+ mUnlockGattServer.addCharacteristic(mUnlockEscrowToken);
+ mUnlockGattServer.addCharacteristic(mUnlockTokenHandle);
+ }
+
+ private synchronized void maybeSendUnlockToken() {
+ if (mCurrentUnlockToken == null || mCurrentUnlockHandle == null) {
+ return;
+ }
+ Log.d(TAG, "Handle and token both received, requesting unlock. Time: "
+ + System.currentTimeMillis());
+ final int callbackCount = mUnlockCallbacks.beginBroadcast();
+ for (int i = 0; i < callbackCount; i++) {
+ try {
+ mUnlockCallbacks.getBroadcastItem(i).onUnlockDataReceived(
+ mCurrentUnlockToken, mCurrentUnlockHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error callback onUnlockDataReceived", e);
+ }
+ }
+ mUnlockCallbacks.finishBroadcast();
+ mCurrentUnlockHandle = null;
+ mCurrentUnlockToken = null;
+ }
+
+ private static byte[] getBytes(long primitive) {
+ ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
+ buffer.putLong(0, primitive);
+ return buffer.array();
+ }
+
+ private static long getLong(byte[] bytes) {
+ ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
+ buffer.put(bytes);
+ buffer.flip();
+ return buffer.getLong();
+ }
+
+ private final class CarTrustAgentBleWrapper extends ICarTrustAgentBleService.Stub {
+ @Override
+ public void registerBleCallback(ICarTrustAgentBleCallback callback) {
+ mBleCallbacks.register(callback);
+ }
+
+ @Override
+ public void unregisterBleCallback(ICarTrustAgentBleCallback callback) {
+ mBleCallbacks.unregister(callback);
+ }
+
+ @Override
+ public void startEnrolmentAdvertising() {
+ Log.d(TAG, "startEnrolmentAdvertising");
+ startAdvertising(mEnrolmentUuid, mEnrolmentGattServer);
+ }
+
+ @Override
+ public void stopEnrolmentAdvertising() {
+ Log.d(TAG, "stopEnrolmentAdvertising");
+ stopAdvertising();
+ }
+
+ @Override
+ public void sendEnrolmentHandle(BluetoothDevice device, long handle) {
+ Log.d(TAG, "sendEnrolmentHandle: " + handle);
+ mEnrolmentTokenHandle.setValue(getBytes(handle));
+ notifyCharacteristicChanged(device, mEnrolmentTokenHandle, false);
+ }
+
+ @Override
+ public void registerEnrolmentCallback(ICarTrustAgentEnrolmentCallback callback) {
+ mEnrolmentCallbacks.register(callback);
+ }
+
+ @Override
+ public void unregisterEnrolmentCallback(ICarTrustAgentEnrolmentCallback callback) {
+ mEnrolmentCallbacks.unregister(callback);
+ }
+
+ @Override
+ public void startUnlockAdvertising() {
+ Log.d(TAG, "startUnlockAdvertising");
+ startAdvertising(mUnlockUuid, mUnlockGattServer);
+ }
+
+ @Override
+ public void stopUnlockAdvertising() {
+ Log.d(TAG, "stopUnlockAdvertising");
+ stopAdvertising();
+ }
+
+ @Override
+ public void registerUnlockCallback(ICarTrustAgentUnlockCallback callback) {
+ mUnlockCallbacks.register(callback);
+ }
+
+ @Override
+ public void unregisterUnlockCallback(ICarTrustAgentUnlockCallback callback) {
+ mUnlockCallbacks.unregister(callback);
+ }
+ }
+}
diff --git a/TrustAgent/src/com/android/car/trust/CarUnlockService.java b/TrustAgent/src/com/android/car/trust/CarUnlockService.java
deleted file mode 100644
index fecfe33c78..0000000000
--- a/TrustAgent/src/com/android/car/trust/CarUnlockService.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.car.trust;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.ParcelUuid;
-import android.util.Log;
-
-import java.util.UUID;
-
-/**
- * A service that receives unlock requests from remote devices.
- */
-public class CarUnlockService extends SimpleBleServer {
-
- private final IBinder mBinder = new UnlockServiceBinder();
-
- private BluetoothGattService mUnlockService;
- private BluetoothGattCharacteristic mUnlockEscrowToken;
- private BluetoothGattCharacteristic mUnlockTokenHandle;
-
- private OnUnlockDeviceListener mOnUnlockDeviceListener;
-
- private byte[] mCurrentToken;
- private Long mCurrentHandle;
-
- public class UnlockServiceBinder extends Binder {
- public CarUnlockService getService() {
- return CarUnlockService.this;
- }
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- setupUnlockService();
- }
-
- /**
- * Start advertising the BLE unlock service
- */
- public void start() {
- ParcelUuid uuid = new ParcelUuid(UUID.fromString(getString(R.string.unlock_service_uuid)));
- Log.d(Utils.LOG_TAG, "CarUnlockService start with uuid: " + uuid);
- start(uuid, mUnlockService, new Handler());
- }
-
- public void setOnUnlockDeviceListener(OnUnlockDeviceListener callback) {
- mOnUnlockDeviceListener = callback;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- @Override
- public void onCharacteristicWrite(BluetoothDevice device,
- int requestId, BluetoothGattCharacteristic characteristic,
- boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
- UUID uuid = characteristic.getUuid();
-
- if (uuid.equals(mUnlockTokenHandle.getUuid())) {
- Log.d(Utils.LOG_TAG, "Unlock handle received, value: " + Utils.getLong(value));
- mCurrentHandle = Utils.getLong(value);
- unlockDataReceived();
- } else if (uuid.equals(mUnlockEscrowToken.getUuid())) {
- Log.d(Utils.LOG_TAG, "Unlock escrow token received, value: " + Utils.getLong(value));
- mCurrentToken = value;
- unlockDataReceived();
- }
- }
-
- @Override
- public void onCharacteristicRead(BluetoothDevice device,
- int requestId, int offset, BluetoothGattCharacteristic characteristic) {
- // The BLE unlock service should not receive any read requests.
- }
-
- private synchronized void unlockDataReceived() {
- // If any piece of the unlocking data is not received, then do not unlock.
- if (mCurrentHandle == null || mCurrentToken == null) {
- return;
- }
-
- Log.d(Utils.LOG_TAG, "Handle and token both received, requesting unlock. Time: "
- + System.currentTimeMillis());
- // Both the handle and token has been received, try to unlock the device.
- mOnUnlockDeviceListener.onUnlockDevice(mCurrentToken, mCurrentHandle);
-
- // Once we've notified the client of the unlocking data, clear it out.
- mCurrentToken = null;
- mCurrentHandle = null;
- }
-
-
- // Create services and characteristics to receive tokens and handles for unlocking the device.
- private void setupUnlockService() {
- mUnlockService = new BluetoothGattService(
- UUID.fromString(getString(R.string.unlock_service_uuid)),
- BluetoothGattService.SERVICE_TYPE_PRIMARY);
-
- // Characteristic to describe the escrow token being used for unlock
- mUnlockEscrowToken = new BluetoothGattCharacteristic(
- UUID.fromString(getString(R.string.unlock_escrow_token_uiid)),
- BluetoothGattCharacteristic.PROPERTY_WRITE,
- BluetoothGattCharacteristic.PERMISSION_WRITE);
-
- // Characteristic to describe the handle being used for this escrow token
- mUnlockTokenHandle = new BluetoothGattCharacteristic(
- UUID.fromString(getString(R.string.unlock_handle_uiid)),
- BluetoothGattCharacteristic.PROPERTY_WRITE,
- BluetoothGattCharacteristic.PERMISSION_WRITE);
-
- mUnlockService.addCharacteristic(mUnlockEscrowToken);
- mUnlockService.addCharacteristic(mUnlockTokenHandle);
- }
-
- /**
- * Interface to send the token to unlock a device
- */
- public interface OnUnlockDeviceListener {
- /**
- * Sends token to unlock the trust device
- * @param token
- * @param handle
- */
- void onUnlockDevice(byte[] token, long handle);
- }
-}
diff --git a/TrustAgent/src/com/android/car/trust/SimpleBleServer.java b/TrustAgent/src/com/android/car/trust/SimpleBleServer.java
index 8c46e24142..7fbf2fedbd 100644
--- a/TrustAgent/src/com/android/car/trust/SimpleBleServer.java
+++ b/TrustAgent/src/com/android/car/trust/SimpleBleServer.java
@@ -37,14 +37,13 @@ import android.os.Handler;
import android.os.ParcelUuid;
import android.util.Log;
-import java.util.HashSet;
-import java.util.Set;
-
/**
* A generic service to start a BLE
*/
public abstract class SimpleBleServer extends Service {
+ private static final String TAG = SimpleBleServer.class.getSimpleName();
+
private static final int BLE_RETRY_LIMIT = 5;
private static final int BLE_RETRY_INTERVAL_MS = 1000;
@@ -52,19 +51,15 @@ public abstract class SimpleBleServer extends Service {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
- Log.d(Utils.LOG_TAG, "Successfully started advertising service");
- for (ConnectionCallback callback : mConnectionCallbacks) {
- callback.onServerStarted();
- }
+ Log.d(TAG, "Successfully started advertising service");
+ onAdvertiseStartSuccess();
}
@Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
- Log.e(Utils.LOG_TAG, "Failed to advertise, errorCode: " + errorCode);
- for (ConnectionCallback callback : mConnectionCallbacks) {
- callback.onServerStartFailed(errorCode);
- }
+ Log.e(TAG, "Failed to advertise, errorCode: " + errorCode);
+ onAdvertiseStartFailure(errorCode);
}
};
@@ -73,46 +68,46 @@ public abstract class SimpleBleServer extends Service {
@Override
public void onConnectionStateChange(BluetoothDevice device,
final int status, final int newState) {
- Log.d(Utils.LOG_TAG, "GattServer connection change status: " + status
+ Log.d(TAG, "GattServer connection change status: " + status
+ " newState: " + newState
+ " device name: " + device.getName());
- if (newState == BluetoothProfile.STATE_CONNECTED) {
- for (ConnectionCallback callback : mConnectionCallbacks) {
- callback.onDeviceConnected(device);
- }
+ switch (newState) {
+ case BluetoothProfile.STATE_CONNECTED:
+ onAdvertiseDeviceConnected(device);
+ break;
+ case BluetoothProfile.STATE_DISCONNECTED:
+ onAdvertiseDeviceDisconnected(device);
+ break;
}
}
@Override
public void onServiceAdded(final int status, BluetoothGattService service) {
- Log.d(Utils.LOG_TAG, "Service added status: " + status + " uuid: " + service.getUuid());
+ Log.d(TAG, "Service added status: " + status + " uuid: " + service.getUuid());
}
@Override
public void onCharacteristicReadRequest(BluetoothDevice device,
int requestId, int offset, final BluetoothGattCharacteristic characteristic) {
- Log.d(Utils.LOG_TAG, "Read request for characteristic: " + characteristic.getUuid());
+ Log.d(TAG, "Read request for characteristic: " + characteristic.getUuid());
mGattServer.sendResponse(device, requestId,
BluetoothGatt.GATT_SUCCESS, offset, characteristic.getValue());
- SimpleBleServer.
- this.onCharacteristicRead(device, requestId, offset, characteristic);
+ onCharacteristicRead(device, requestId, offset, characteristic);
}
@Override
public void onCharacteristicWriteRequest(final BluetoothDevice device, int requestId,
BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
responseNeeded, int offset, byte[] value) {
- Log.d(Utils.LOG_TAG, "Write request for characteristic: " + characteristic.getUuid());
+ Log.d(TAG, "Write request for characteristic: " + characteristic.getUuid());
mGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS,
offset, value);
-
- SimpleBleServer.
- this.onCharacteristicWrite(device, requestId, characteristic,
+ onCharacteristicWrite(device, requestId, characteristic,
preparedWrite, responseNeeded, offset, value);
}
};
- private final Set<ConnectionCallback> mConnectionCallbacks = new HashSet<>();
+ private final Handler mHandler = new Handler();
private BluetoothManager mBluetoothManager;
private BluetoothLeAdvertiser mAdvertiser;
@@ -127,19 +122,17 @@ public abstract class SimpleBleServer extends Service {
*
* @param advertiseUuid Service Uuid used in the {@link AdvertiseData}
* @param service {@link BluetoothGattService} that will be discovered by clients
- * @param handler {@link Handler} instance to run the retry logic
*/
- protected void start(ParcelUuid advertiseUuid, BluetoothGattService service,
- Handler handler) {
+ protected void startAdvertising(ParcelUuid advertiseUuid, BluetoothGattService service) {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
- Log.e(Utils.LOG_TAG, "System does not support BLE");
+ Log.e(TAG, "System does not support BLE");
return;
}
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mGattServer = mBluetoothManager.openGattServer(this, mGattServerCallback);
if (mGattServer == null) {
- Log.e(Utils.LOG_TAG, "Gatt Server not created");
+ Log.e(TAG, "Gatt Server not created");
return;
}
@@ -160,27 +153,41 @@ public abstract class SimpleBleServer extends Service {
.build();
mAdvertiserStartCount = 0;
- startAdvertisingInternally(settings, data, handler);
+ startAdvertisingInternally(settings, data);
}
- private void startAdvertisingInternally(AdvertiseSettings settings,
- AdvertiseData data, Handler handler) {
+ private void startAdvertisingInternally(AdvertiseSettings settings, AdvertiseData data) {
mAdvertiserStartCount += 1;
mAdvertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
if (mAdvertiser == null && mAdvertiserStartCount < BLE_RETRY_LIMIT) {
- handler.postDelayed(() -> startAdvertisingInternally(settings, data, handler),
+ mHandler.postDelayed(() -> startAdvertisingInternally(settings, data),
BLE_RETRY_INTERVAL_MS);
} else {
- handler.removeCallbacks(null);
+ mHandler.removeCallbacks(null);
mAdvertiser.startAdvertising(settings, data, mAdvertisingCallback);
mAdvertiserStartCount = 0;
}
}
+ protected void stopAdvertising() {
+ if (mAdvertiser != null) {
+ mAdvertiser.stopAdvertising(mAdvertisingCallback);
+ }
+ }
+
/**
- * Stops the advertiser and GATT server. This needs to be done to avoid leaks
+ * Notifies the characteristic change via {@link BluetoothGattServer}
*/
- protected void stop() {
+ protected void notifyCharacteristicChanged(BluetoothDevice device,
+ BluetoothGattCharacteristic characteristic, boolean confirm) {
+ if (mGattServer != null) {
+ mGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ // Stops the advertiser and GATT server. This needs to be done to avoid leaks
if (mAdvertiser != null) {
mAdvertiser.stopAdvertising(mAdvertisingCallback);
mAdvertiser.cleanup();
@@ -193,73 +200,32 @@ public abstract class SimpleBleServer extends Service {
mGattServer.cancelConnection(d);
}
} catch (UnsupportedOperationException e) {
- Log.e(Utils.LOG_TAG, "Error getting connected devices", e);
+ Log.e(TAG, "Error getting connected devices", e);
} finally {
mGattServer.close();
}
}
-
- mConnectionCallbacks.clear();
- }
-
- /**
- * Notifies the characteristic change via {@link BluetoothGattServer}
- */
- protected boolean notifyCharacteristicChanged(BluetoothDevice device,
- BluetoothGattCharacteristic characteristic, boolean confirm) {
- return (mGattServer != null)
- && mGattServer.notifyCharacteristicChanged(device, characteristic, confirm);
- }
-
- @Override
- public void onDestroy() {
- stop();
super.onDestroy();
}
- public void registerConnectionCallback(ConnectionCallback callback) {
- Log.d(Utils.LOG_TAG, "Adding connection listener");
- mConnectionCallbacks.add(callback);
- }
-
- public void unregisterConnectionCallback(ConnectionCallback callback) {
- mConnectionCallbacks.remove(callback);
- }
+ // Delegate to subclass
+ protected void onAdvertiseStartSuccess() { }
+ protected void onAdvertiseStartFailure(int errorCode) { }
+ protected void onAdvertiseDeviceConnected(BluetoothDevice device) { }
+ protected void onAdvertiseDeviceDisconnected(BluetoothDevice device) { }
/**
* Triggered when this BleService receives a write request from a remote
* device. Sub-classes should implement how to handle requests.
*/
- public abstract void onCharacteristicWrite(final BluetoothDevice device, int requestId,
+ protected abstract void onCharacteristicWrite(BluetoothDevice device, int requestId,
BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean
responseNeeded, int offset, byte[] value);
/**
* Triggered when this BleService receives a read request from a remote device.
*/
- public abstract void onCharacteristicRead(BluetoothDevice device,
+ protected abstract void onCharacteristicRead(BluetoothDevice device,
int requestId, int offset, final BluetoothGattCharacteristic characteristic);
- /**
- * Callback that is notified when the status of the BLE server changes.
- */
- public interface ConnectionCallback {
- /**
- * Called when the GATT server is started and BLE is successfully advertising.
- */
- void onServerStarted();
-
- /**
- * Called when the BLE advertisement fails to start.
- *
- * @param errorCode Error code (see {@link AdvertiseCallback}#ADVERTISE_FAILED_* constants)
- */
- void onServerStartFailed(int errorCode);
-
- /**
- * Called when a device is connected.
- * @param device {@link BluetoothDevice} that is connected
- */
- void onDeviceConnected(BluetoothDevice device);
- }
}
diff --git a/TrustAgent/src/com/android/car/trust/Utils.java b/TrustAgent/src/com/android/car/trust/Utils.java
deleted file mode 100644
index 9f63cc4a22..0000000000
--- a/TrustAgent/src/com/android/car/trust/Utils.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.car.trust;
-
-import java.nio.ByteBuffer;
-
-public class Utils {
-
- public static final String LOG_TAG = "CarTrustAgentService";
-
- public static byte[] getBytes(long l) {
- ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
- buffer.putLong(0, l);
- return buffer.array();
- }
-
- public static long getLong(byte[] bytes) {
- ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE);
- buffer.put(bytes);
- buffer.flip();
- return buffer.getLong();
- }
-}