summaryrefslogtreecommitdiff
path: root/SetupWizard/src
diff options
context:
space:
mode:
Diffstat (limited to 'SetupWizard/src')
-rw-r--r--SetupWizard/src/com/android/car/setupwizard/bluetooth/BluetoothActivity.java427
-rw-r--r--SetupWizard/src/com/android/car/setupwizard/bluetooth/BluetoothDeviceHierarchy.java277
2 files changed, 0 insertions, 704 deletions
diff --git a/SetupWizard/src/com/android/car/setupwizard/bluetooth/BluetoothActivity.java b/SetupWizard/src/com/android/car/setupwizard/bluetooth/BluetoothActivity.java
deleted file mode 100644
index 734e1ee..0000000
--- a/SetupWizard/src/com/android/car/setupwizard/bluetooth/BluetoothActivity.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2017 Google Inc.
- *
- * 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.setupwizard.bluetooth;
-
-import static com.android.setupwizardlib.util.ResultCodes.RESULT_SKIP;
-
-import android.app.Activity;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.util.Log;
-import android.view.View;
-
-import com.android.car.setupwizard.R;
-import com.android.car.setupwizard.bluetooth.BluetoothDeviceHierarchy.BluetoothItem;
-
-import com.android.setupwizardlib.GlifRecyclerLayout;
-import com.android.setupwizardlib.items.IItem;
-import com.android.setupwizardlib.items.Item;
-import com.android.setupwizardlib.items.ItemGroup;
-import com.android.setupwizardlib.items.RecyclerItemAdapter;
-import com.android.setupwizardlib.util.ResultCodes;
-import com.android.setupwizardlib.util.WizardManagerHelper;
-
-/**
- * An Activity that presents the option for the user to pair the current device to a nearby
- * bluetooth device. This screen will list the devices in the order that they are discovered
- * as well as an option to not pair at all.
- */
-public class BluetoothActivity extends Activity
- implements RecyclerItemAdapter.OnItemSelectedListener {
- private static final String TAG = "BluetoothActivity";
-
- /**
- * This value is copied from {@code com.google.android.setupwizard.BaseActivity}. Wizard
- * Manager does not actually return an activity result, but if we invoke Wizard Manager without
- * requesting a result, the framework will choose not to issue a call to onActivityResult with
- * RESULT_CANCELED when navigating backward.
- */
- private static final int REQUEST_CODE_NEXT = 10000;
-
- private static final int BLUETOOTH_SCAN_RETRY_DELAY = 1000;
- private static final int MAX_BLUETOOTH_SCAN_RETRIES = 3;
-
- private final Handler mHandler = new Handler();
- private int mScanRetryCount;
-
- private BluetoothScanReceiver mScanReceiver;
- private BluetoothAdapterReceiver mAdapterReceiver;
- private BluetoothAdapter mAdapter;
- private BluetoothDeviceHierarchy mBluetoothDeviceHierarchy;
-
- private GlifRecyclerLayout mLayout;
- private Item mScanningIndicator;
- private Item mRescanIndicator;
-
- /**
- * The current {@link BluetoothDevice} that is being paired to.
- */
- private BluetoothDevice mCurrentBondingDevice;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mAdapter = BluetoothAdapter.getDefaultAdapter();
-
- if (mAdapter == null) {
- Log.w(TAG, "No bluetooth adapter found on the device. Skipping to next action.");
- nextAction(RESULT_SKIP);
- return;
- }
-
- setContentView(R.layout.bluetooth_activity);
-
- mLayout = (GlifRecyclerLayout) findViewById(R.id.setup_wizard_layout);
-
- RecyclerItemAdapter adapter = (RecyclerItemAdapter) mLayout.getAdapter();
- adapter.setOnItemSelectedListener(this);
-
- ItemGroup hierarchy = (ItemGroup) adapter.getRootItemHierarchy();
- mBluetoothDeviceHierarchy =
- (BluetoothDeviceHierarchy) hierarchy.findItemById(R.id.bluetooth_device_list);
- mScanningIndicator = (Item) hierarchy.findItemById(R.id.bluetooth_scanning);
- mRescanIndicator = (Item) hierarchy.findItemById(R.id.bluetooth_rescan);
-
- Item descriptionItem = (Item) hierarchy.findItemById(R.id.bluetooth_description);
- descriptionItem.setTitle(getText(R.string.bluetooth_description));
-
- // Assume that a search will be started, so display the progress bar to let the user
- // know that something is going on.
- mLayout.setProgressBarShown(true);
-
- if (mAdapter.isEnabled()) {
- setUpAndStartScan();
- } else {
- mAdapterReceiver = new BluetoothAdapterReceiver();
- maybeRegisterAdapterReceiver();
- mAdapter.enable();
- }
- }
-
- @Override
- protected void onStart() {
- super.onStart();
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onStart()");
- }
-
- if (mAdapter == null) {
- Log.w(TAG, "No bluetooth adapter found on the device. Skipping to next action.");
- nextAction(RESULT_SKIP);
- return;
- }
-
- maybeRegisterAdapterReceiver();
- registerScanReceiver();
- }
-
- @Override
- protected void onStop() {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "onStop()");
- }
-
- stopScanning();
-
- if (mScanReceiver != null) {
- unregisterReceiver(mScanReceiver);
- }
-
- if (mAdapterReceiver != null) {
- unregisterReceiver(mAdapterReceiver);
- }
-
- super.onStop();
- }
-
- /**
- * Sets up an Intent filter to listen for bluetooth state changes and initiates a scan for
- * nearby bluetooth devices.
- */
- private void setUpAndStartScan() {
- mBluetoothDeviceHierarchy.clearAllDevices();
- registerScanReceiver();
- startScanning();
- }
-
- /**
- * Registers a receiver to be listen on changes to the {@link BluetoothAdapter}. This method
- * will only register the receiver if {@link #mAdapterReceiver} is not {@code null}.
- */
- private void maybeRegisterAdapterReceiver() {
- if (mAdapterReceiver == null) {
- return;
- }
-
- IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
- registerReceiver(mAdapterReceiver, filter);
- }
-
- /**
- * Registers an Intent filter to listen for the results of a bluetooth discovery scan as well as
- * changes to individual bluetooth devices.
- */
- private void registerScanReceiver() {
- if (mScanReceiver == null) {
- mScanReceiver = new BluetoothScanReceiver();
- }
-
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
- intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
- intentFilter.addAction(BluetoothDevice.ACTION_NAME_CHANGED);
- intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
- registerReceiver(mScanReceiver, intentFilter);
- }
-
- /**
- * Start a scan for nearby bluetooth devices. If the call to
- * {@link BluetoothAdapter#startDiscovery()} fails, then this method will retry the call after
- * an exponential backoff period based on {@link #BLUETOOTH_SCAN_RETRY_DELAY}.
- *
- * <p>If there is already a bluetooth scan in progress when this function is called, then this
- * function will do nothing.
- */
- private void startScanning() {
- if (mAdapter.isDiscovering()) {
- return;
- }
-
- boolean success = mAdapter.startDiscovery();
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "startDiscovery() success: " + success);
- }
-
- // If a scan fails, attempt to try again up to MAX_BLUETOOTH_SCAN_RETRIES tries.
- if (success) {
- mScanRetryCount = 0;
- } else if (mScanRetryCount >= MAX_BLUETOOTH_SCAN_RETRIES) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Reached max retries to initiate a bluetooth scan. Moving onto next "
- + "action");
- }
-
- nextAction(RESULT_SKIP);
- } else {
- mHandler.postDelayed(this::startScanning,
- BLUETOOTH_SCAN_RETRY_DELAY * ++mScanRetryCount);
- }
- }
-
- /**
- * Stops any scan in that is currently in progress for nearby bluetooth devices.
- */
- private void stopScanning() {
- if (mAdapter != null && mAdapter.isDiscovering()) {
- mAdapter.cancelDiscovery();
- }
-
- mScanRetryCount = 0;
- }
-
- @Override
- public void onItemSelected(IItem item) {
- if (item instanceof BluetoothItem) {
- pairOrUnpairDevice((BluetoothItem) item);
- return;
- }
-
- if (!(item instanceof Item)) {
- return;
- }
-
- switch (((Item) item).getId()) {
- case R.id.bluetooth_dont_connect:
- nextAction(RESULT_SKIP);
- break;
-
- case R.id.bluetooth_rescan:
- stopScanning();
- startScanning();
- break;
-
- default:
- Log.w(TAG, "Unknown item clicked: " + item);
- }
- }
-
- /**
- * Starts a pairing or unpairing session with the given device based on its current bonded
- * state. For example, if the current item is already paired, it is unpaired and vice versa.
- */
- private void pairOrUnpairDevice(BluetoothItem item) {
- // Pairing is unreliable while scanning, so cancel discovery.
- stopScanning();
-
- BluetoothDevice device = item.getBluetoothDevice();
-
- boolean success;
- switch (device.getBondState()) {
- case BluetoothDevice.BOND_BONDED:
- mCurrentBondingDevice = null;
- success = device.removeBond();
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "removeBond() to device (" + device + ") successful: " + success);
- }
-
- // Immediately update the UI so that the user has feedback on their actions.
- item.updateConnectionState(this /* context */,
- BluetoothItem.CONNECTION_STATE_DISCONNECTING);
- break;
-
- case BluetoothDevice.BOND_BONDING:
- mCurrentBondingDevice = null;
- success = device.cancelBondProcess();
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "cancelBondProcess() to device (" + device + ") successful: "
- + success);
- }
-
- // Immediately update the UI so that the user has feedback on their actions.
- item.updateConnectionState(this /* context */,
- BluetoothItem.CONNECTION_STATE_CANCELLING);
- break;
-
- case BluetoothDevice.BOND_NONE:
- mCurrentBondingDevice = device;
- success = device.createBond();
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "createBond() to device (" + device + ") successful: " + success);
- }
-
- // Immediately update the UI so that the user has feedback on their actions.
- item.updateConnectionState(this /* context */,
- BluetoothItem.CONNECTION_STATE_CONNECTING);
-
- default:
- Log.w(TAG, "Encountered unknown bond state: " + device.getBondState());
- }
- }
-
- private void nextAction(int resultCode) {
- setResult(resultCode);
- Intent nextIntent = WizardManagerHelper.getNextIntent(getIntent(), resultCode);
- startActivityForResult(nextIntent, REQUEST_CODE_NEXT);
- }
-
- /**
- * A {@link BroadReceiver} that listens for when the bluetooth adapter has been turned on.
- */
- private class BluetoothAdapterReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- if (action != null && action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
- int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
- BluetoothAdapter.ERROR);
-
- if (state == BluetoothAdapter.STATE_ON) {
- setUpAndStartScan();
- }
- }
- }
- }
-
- /**
- * Handles bluetooth scan responses and other indicators.
- **/
- private class BluetoothScanReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- if (action == null) {
- return;
- }
-
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Received device: " + device);
- }
-
- switch (action) {
- case BluetoothDevice.ACTION_FOUND:
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Bluetooth device found");
- }
-
- mLayout.setProgressBarShown(false);
- mScanningIndicator.setVisible(false);
- mRescanIndicator.setVisible(true);
- mBluetoothDeviceHierarchy.addOrUpdateDevice(context, device);
- break;
-
- case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Bluetooth discovery started");
- }
-
- mLayout.setProgressBarShown(true);
- mScanningIndicator.setVisible(true);
- mRescanIndicator.setVisible(false);
- mBluetoothDeviceHierarchy.clearAllDevices();
- break;
-
- case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Bluetooth discovery finished");
- }
- break;
-
- case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Bluetooth bond state changed");
- }
-
- mBluetoothDeviceHierarchy.addOrUpdateDevice(context, device);
-
- // When a bluetooth device has been paired, then move onto the next action so
- // the user is not stuck on this screen for too long.
- if (device.equals(mCurrentBondingDevice)
- && device.getBondState() == BluetoothDevice.BOND_BONDED) {
- nextAction(RESULT_OK);
- }
- break;
-
- case BluetoothDevice.ACTION_NAME_CHANGED:
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Bluetooth device name chaged");
- }
- mBluetoothDeviceHierarchy.addOrUpdateDevice(context, device);
- break;
-
- default:
- Log.w(TAG, "Unknown action received: " + action);
- }
- }
- }
-}
diff --git a/SetupWizard/src/com/android/car/setupwizard/bluetooth/BluetoothDeviceHierarchy.java b/SetupWizard/src/com/android/car/setupwizard/bluetooth/BluetoothDeviceHierarchy.java
deleted file mode 100644
index 02f76bf..0000000
--- a/SetupWizard/src/com/android/car/setupwizard/bluetooth/BluetoothDeviceHierarchy.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2017 Google Inc.
- *
- * 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.setupwizard.bluetooth;
-
-import android.bluetooth.BluetoothClass.Device;
-import android.bluetooth.BluetoothDevice;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.IntDef;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-
-import com.android.car.setupwizard.R;
-
-import com.android.setupwizardlib.items.AbstractItemHierarchy;
-import com.android.setupwizardlib.items.IItem;
-import com.android.setupwizardlib.items.Item;
-import com.android.setupwizardlib.items.ItemHierarchy;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * An item hierarchy that represents a list of Bluetooth devices.
- */
-public class BluetoothDeviceHierarchy extends AbstractItemHierarchy {
- private static final String TAG = "BtDeviceHierarchy";
-
- /**
- * A set of all discovered bluetooth devices. The key of this map is the device's MAC address.
- */
- private final HashMap<String, BluetoothItem> mItems = new HashMap<>();
-
- /**
- * A list of all discovered bluetooth devices' MAC addresses. This list is sorted in the order
- * that the devices were discovered in.
- */
- private final List<String> mAddresses = new ArrayList<>();
-
- public BluetoothDeviceHierarchy(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- /**
- * Clears the current list of all bluetooth devices.
- */
- public void clearAllDevices() {
- mItems.clear();
- mAddresses.clear();
- notifyChanged();
- }
-
- /**
- * Adds the given {@link BluetoothDevice} to be displayed. If the device has already been
- * added before, its information is updated based on the given {@code BluetoothDevice}.
- */
- public void addOrUpdateDevice(Context context, @Nullable BluetoothDevice device) {
- if (device == null) {
- return;
- }
-
- String address = device.getAddress();
- BluetoothItem item;
-
- if (mItems.containsKey(address)) {
- item = mItems.get(address);
- } else {
- // First time encountering this address, so keep track of it.
- mAddresses.add(address);
-
- int id = View.generateViewId();
- if (id >= 0x00ffffff) {
- // View.generateViewId returns an incrementing number from 1 to 0x00ffffff.
- // Since we are generating view IDs without recycling, it is theoretically possible
- // for the ID space to run out if the user encounters enough bluetooth devices.
- // Just log if this happens.
- Log.e(TAG, "Ran out of IDs to use for bluetooth item IDs");
- }
- item = new BluetoothItem(id);
- }
-
- item.update(context, device);
- mItems.put(address, item);
-
- notifyChanged();
- }
-
- @Override
- public ItemHierarchy findItemById(int id) {
- if (id == getId()) {
- return this;
- }
-
- // Child items have generated hash code IDs. Don't try to find those.
- return null;
- }
-
- @Override
- public int getCount() {
- return mItems.size();
- }
-
- @Override
- public IItem getItemAt(int position) {
- return mItems.get(mAddresses.get(position));
- }
-
- /**
- * A {@link Item} that is linked to a particular {@link BluetoothDevice} and is responsible
- * for binding this information to a View to be displayed.
- */
- public static class BluetoothItem extends Item {
- private BluetoothDevice mDevice;
-
- /**
- * Whether or not the icon for this particular BluetoothDevice has been updated to reflect
- * the type of Bluetooth device this is.
- */
- private boolean mIconUpdated;
-
- public static final int CONNECTION_STATE_DISCONNECTING = 0;
- public static final int CONNECTION_STATE_CONNECTING = 1;
- public static final int CONNECTION_STATE_CANCELLING = 2;
-
- @IntDef({
- CONNECTION_STATE_DISCONNECTING,
- CONNECTION_STATE_CONNECTING,
- CONNECTION_STATE_CANCELLING })
- public @interface ConnectionState {}
-
- public BluetoothItem(int id) {
- setId(id);
- }
-
- /**
- * Immediately updates the connection state of the device that is represented by this
- * {@link BluetoothItem}. This state is not necessarily tied to the bonded state that
- * will be returned by the {@link BluetoothDevice} associated with this item.
- */
- public void updateConnectionState(Context context, @ConnectionState int state) {
- if (mDevice == null) {
- return;
- }
-
- switch (state) {
- case CONNECTION_STATE_DISCONNECTING:
- setSummary(context.getString(R.string.bluetooth_device_disconnecting));
- break;
-
- case CONNECTION_STATE_CONNECTING:
- setSummary(context.getString(R.string.bluetooth_device_connecting));
- break;
-
- case CONNECTION_STATE_CANCELLING:
- setSummary(context.getString(R.string.bluetooth_device_cancelling));
- break;
-
- default:
- // Do nothing.
- }
- }
-
- /**
- * Associate a {@link BluetoothDevice} with this {@link BluetoothItem}.
- */
- public void update(Context context, BluetoothDevice device) {
- mIconUpdated = false;
- mDevice = device;
-
- String name = mDevice.getName();
- setTitle(TextUtils.isEmpty(name) ? mDevice.getAddress() : name);
-
- switch (mDevice.getBondState()) {
- case BluetoothDevice.BOND_BONDED:
- setSummary(context.getString(R.string.bluetooth_device_connected));
- break;
-
- case BluetoothDevice.BOND_BONDING:
- setSummary(context.getString(R.string.bluetooth_device_connecting));
- break;
-
- default:
- setSummary(null);
- }
- }
-
- /**
- * Returns the {@link BluetoothDevice} set via {@link #update(Context, BluetoothDevice)}.
- */
- public BluetoothDevice getBluetoothDevice() {
- return mDevice;
- }
-
- @Override
- public void onBindView(View view) {
- if (mIconUpdated && getIcon() != null) {
- super.onBindView(view);
- return;
- }
-
- Context context = view.getContext();
- TypedArray a = context.obtainStyledAttributes(
- new int[] { R.attr.suwListItemIconColor });
-
- try {
- ColorStateList bluetoothIconColor = a.getColorStateList(0);
- Drawable bluetoothIcon = getDeviceIcon(context).mutate();
- bluetoothIcon.setTintList(bluetoothIconColor);
- setIcon(bluetoothIcon);
- } finally {
- a.recycle();
- }
-
- mIconUpdated = true;
-
- super.onBindView(view);
- }
-
- /**
- * Returns an appropriate {@link Drawable} to use as the icon for the bluetooth device
- * associated with this {@link BluetoothItem}.
- */
- private Drawable getDeviceIcon(Context context) {
- if (mDevice == null) {
- return context.getDrawable(R.drawable.ic_bluetooth_item);
- }
-
- @DrawableRes int deviceIcon;
- switch (mDevice.getBluetoothClass().getDeviceClass()) {
- case Device.AUDIO_VIDEO_HEADPHONES:
- case Device.AUDIO_VIDEO_WEARABLE_HEADSET:
- deviceIcon = R.drawable.ic_headset;
- break;
-
- case Device.COMPUTER_DESKTOP:
- case Device.COMPUTER_LAPTOP:
- deviceIcon = R.drawable.ic_computer;
- break;
-
- case Device.PHONE_SMART:
- deviceIcon = R.drawable.ic_smartphone;
- break;
-
- case Device.WEARABLE_WRIST_WATCH:
- deviceIcon = R.drawable.ic_watch;
- break;
-
- default:
- deviceIcon = R.drawable.ic_bluetooth_item;
- }
-
- return context.getDrawable(deviceIcon);
- }
- }
-}