Settings: use foreground receiver for BT connect am: 2dbe436a43 am: 9a85a9ca1e
am: 9323a3454f
Change-Id: I393ac715b1e6eb23ca3c734b3bb583b5b49156d4
diff --git a/Settings/src/com/android/tv/settings/MainFragment.java b/Settings/src/com/android/tv/settings/MainFragment.java
index b196997..ed2ff2a 100644
--- a/Settings/src/com/android/tv/settings/MainFragment.java
+++ b/Settings/src/com/android/tv/settings/MainFragment.java
@@ -321,6 +321,12 @@
}
final Set<BluetoothDevice> bondedDevices = mBtAdapter.getBondedDevices();
+ if (bondedDevices == null) {
+ mAccessoriesGroup.setVisible(false);
+ mAccessoriesGroup.removeAll();
+ return;
+ }
+
final Set<String> connectedBluetoothAddresses =
BluetoothConnectionsManager.getConnectedSet(getContext());
final Context themedContext = getPreferenceManager().getContext();
@@ -331,26 +337,32 @@
}
for (final BluetoothDevice device : bondedDevices) {
- final String desc = connectedBluetoothAddresses.contains(device.getAddress())
- ? getString(R.string.accessory_connected)
- : null;
+ final String deviceAddress = device.getAddress();
+ if (TextUtils.isEmpty(deviceAddress)) {
+ Log.w(TAG, "Skipping mysteriously empty bluetooth device");
+ continue;
+ }
- final String key = "BluetoothDevice:" + device.getAddress();
+ final String key = "BluetoothDevice:" + deviceAddress;
touchedKeys.add(key);
Preference preference = mAccessoriesGroup.findPreference(key);
if (preference == null) {
preference = new Preference(themedContext);
preference.setKey(key);
}
- preference.setTitle(device.getName());
+ final String deviceName = device.getName();
+ preference.setTitle(deviceName);
+ final String desc = connectedBluetoothAddresses.contains(deviceAddress)
+ ? getString(R.string.accessory_connected)
+ : null;
preference.setSummary(desc);
final int deviceImgId = AccessoryUtils.getImageIdForDevice(device);
preference.setIcon(deviceImgId);
preference.setFragment(BluetoothAccessoryFragment.class.getName());
BluetoothAccessoryFragment.prepareArgs(
preference.getExtras(),
- device.getAddress(),
- device.getName(),
+ deviceAddress,
+ deviceName,
deviceImgId);
mAccessoriesGroup.addPreference(preference);
}
diff --git a/Settings/src/com/android/tv/settings/accessories/AccessoryUtils.java b/Settings/src/com/android/tv/settings/accessories/AccessoryUtils.java
index 5378873..33449c7 100644
--- a/Settings/src/com/android/tv/settings/accessories/AccessoryUtils.java
+++ b/Settings/src/com/android/tv/settings/accessories/AccessoryUtils.java
@@ -19,6 +19,7 @@
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.support.annotation.DrawableRes;
+import android.support.annotation.NonNull;
import com.android.tv.settings.R;
@@ -26,8 +27,13 @@
* Provide utilities for Remote & Accessories.
*/
public class AccessoryUtils {
- public static @DrawableRes int getImageIdForDevice(BluetoothDevice dev) {
- int devClass = dev.getBluetoothClass().getDeviceClass();
+ public static @DrawableRes int getImageIdForDevice(@NonNull BluetoothDevice dev) {
+ final BluetoothClass bluetoothClass = dev.getBluetoothClass();
+ if (bluetoothClass == null) {
+ return R.drawable.ic_bluetooth;
+ }
+
+ final int devClass = bluetoothClass.getDeviceClass();
if (devClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET) {
return R.drawable.ic_headset_mic;
diff --git a/Settings/src/com/android/tv/settings/accessories/AddAccessoryPreferenceFragment.java b/Settings/src/com/android/tv/settings/accessories/AddAccessoryPreferenceFragment.java
index dac821d..229bcfe 100644
--- a/Settings/src/com/android/tv/settings/accessories/AddAccessoryPreferenceFragment.java
+++ b/Settings/src/com/android/tv/settings/accessories/AddAccessoryPreferenceFragment.java
@@ -60,6 +60,10 @@
screen.removeAll();
}
+ if (devices == null) {
+ return;
+ }
+
// Add entries for the discovered Bluetooth devices
for (BluetoothDevice bt : devices) {
final Preference preference = new Preference(themedContext);
diff --git a/Settings/src/com/android/tv/settings/accessories/BluetoothAccessoryFragment.java b/Settings/src/com/android/tv/settings/accessories/BluetoothAccessoryFragment.java
index bf66695..8a5e228 100644
--- a/Settings/src/com/android/tv/settings/accessories/BluetoothAccessoryFragment.java
+++ b/Settings/src/com/android/tv/settings/accessories/BluetoothAccessoryFragment.java
@@ -16,6 +16,7 @@
package com.android.tv.settings.accessories;
+import android.app.Fragment;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
@@ -41,6 +42,7 @@
import com.android.tv.settings.R;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@@ -58,6 +60,7 @@
private static final int UNPAIR_TIMEOUT = 5000;
+ private static final String ARG_DEVICE = "device";
private static final String ARG_ACCESSORY_ADDRESS = "accessory_address";
private static final String ARG_ACCESSORY_NAME = "accessory_name";
private static final String ARG_ACCESSORY_ICON_ID = "accessory_icon_res";
@@ -82,30 +85,7 @@
};
// Broadcast Receiver for Bluetooth related events
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- BluetoothDevice device = intent
- .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (mUnpairing) {
- if (mDevice.equals(device)) {
- // Done removing device, finish the activity
- mMsgHandler.removeCallbacks(mTimeoutRunnable);
- navigateBack();
- }
- }
- }
- };
-
- // Internal message handler
- private final Handler mMsgHandler = new Handler();
-
- private final Runnable mTimeoutRunnable = new Runnable() {
- @Override
- public void run() {
- navigateBack();
- }
- };
+ private BroadcastReceiver mBroadcastReceiver;
public static BluetoothAccessoryFragment newInstance(String deviceAddress, String deviceName,
int deviceImgId) {
@@ -141,11 +121,13 @@
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter != null) {
- Set<BluetoothDevice> bondedDevices = btAdapter.getBondedDevices();
- for (BluetoothDevice device : bondedDevices) {
- if (mDeviceAddress.equals(device.getAddress())) {
- mDevice = device;
- break;
+ final Set<BluetoothDevice> bondedDevices = btAdapter.getBondedDevices();
+ if (bondedDevices != null) {
+ for (BluetoothDevice device : bondedDevices) {
+ if (mDeviceAddress.equals(device.getAddress())) {
+ mDevice = device;
+ break;
+ }
}
}
}
@@ -167,11 +149,11 @@
mDeviceGatt = mDevice.connectGatt(getActivity(), true, new GattBatteryCallbacks());
}
// Set a broadcast receiver to let us know when the device has been removed
- IntentFilter adapterIntentFilter = new IntentFilter();
+ final IntentFilter adapterIntentFilter = new IntentFilter();
adapterIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
+ mBroadcastReceiver = new UnpairReceiver(this, mDevice);
getActivity().registerReceiver(mBroadcastReceiver, adapterIntentFilter);
if (mDevice != null && mDevice.getBondState() == BluetoothDevice.BOND_NONE) {
- mMsgHandler.removeCallbacks(mTimeoutRunnable);
navigateBack();
}
}
@@ -207,7 +189,8 @@
mUnpairPref = new Preference(themedContext);
updateUnpairPref(mUnpairPref);
mUnpairPref.setFragment(UnpairConfirmFragment.class.getName());
- UnpairConfirmFragment.prepareArgs(mUnpairPref.getExtras(), mDeviceName, mDeviceImgId);
+ UnpairConfirmFragment.prepareArgs(
+ mUnpairPref.getExtras(), mDevice, mDeviceName, mDeviceImgId);
screen.addPreference(mUnpairPref);
mBatteryPref = new Preference(themedContext);
@@ -217,6 +200,11 @@
setPreferenceScreen(screen);
}
+ public void setUnpairing(boolean unpairing) {
+ mUnpairing = unpairing;
+ updateUnpairPref(mUnpairPref);
+ }
+
private void updateUnpairPref(Preference pref) {
if (mUnpairing) {
pref.setTitle(R.string.accessory_unpairing);
@@ -233,37 +221,6 @@
mHandler.post(mBailoutRunnable);
}
- private void unpairDevice() {
- if (mDevice != null) {
- int state = mDevice.getBondState();
-
- if (state == BluetoothDevice.BOND_BONDING) {
- mDevice.cancelBondProcess();
- }
-
- if (state != BluetoothDevice.BOND_NONE) {
- mUnpairing = true;
- // Set a timeout, just in case we don't receive the unpair notification we
- // use to finish the activity
- mMsgHandler.postDelayed(mTimeoutRunnable, UNPAIR_TIMEOUT);
- final boolean successful = mDevice.removeBond();
- if (successful) {
- if (DEBUG) {
- Log.d(TAG, "Bluetooth device successfully unpaired.");
- }
- // set the dialog to a waiting state
- if (mUnpairPref != null) {
- updateUnpairPref(mUnpairPref);
- }
- } else {
- Log.e(TAG, "Failed to unpair Bluetooth Device: " + mDevice.getName());
- }
- }
- } else {
- Log.e(TAG, "Bluetooth device not found. Address = " + mDeviceAddress);
- }
- }
-
private class GattBatteryCallbacks extends BluetoothGattCallback {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
@@ -317,7 +274,7 @@
if (GATT_BATTERY_LEVEL_CHARACTERISTIC_UUID.equals(characteristic.getUuid())) {
final int batteryLevel =
characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
- mMsgHandler.post(new Runnable() {
+ mHandler.post(new Runnable() {
@Override
public void run() {
if (mBatteryPref != null && !mUnpairing) {
@@ -331,14 +288,96 @@
}
}
+ private static class UnpairReceiver extends BroadcastReceiver {
+
+ private final Fragment mFragment;
+ private final BluetoothDevice mDevice;
+
+ public UnpairReceiver(Fragment fragment, BluetoothDevice device) {
+ mFragment = fragment;
+ mDevice = device;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final BluetoothDevice device = intent
+ .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ final int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
+ BluetoothDevice.BOND_NONE);
+ if (bondState == BluetoothDevice.BOND_NONE && Objects.equals(mDevice, device)) {
+ // Device was removed, bail out of the fragment
+ if (mFragment instanceof BluetoothAccessoryFragment) {
+ ((BluetoothAccessoryFragment) mFragment).navigateBack();
+ } else if (mFragment instanceof UnpairConfirmFragment) {
+ ((UnpairConfirmFragment) mFragment).navigateBack();
+ } else {
+ throw new IllegalStateException(
+ "UnpairReceiver attached to wrong fragment class");
+ }
+ }
+ }
+ }
+
public static class UnpairConfirmFragment extends GuidedStepFragment {
- public static void prepareArgs(@NonNull Bundle args, String deviceName,
- @DrawableRes int deviceImgId) {
+ private BluetoothDevice mDevice;
+ private BroadcastReceiver mBroadcastReceiver;
+ private final Handler mHandler = new Handler();
+
+ private Runnable mBailoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (isResumed() && !getFragmentManager().popBackStackImmediate()) {
+ getActivity().onBackPressed();
+ }
+ }
+ };
+
+ private final Runnable mTimeoutRunnable = new Runnable() {
+ @Override
+ public void run() {
+ navigateBack();
+ }
+ };
+
+ public static void prepareArgs(@NonNull Bundle args, BluetoothDevice device,
+ String deviceName, @DrawableRes int deviceImgId) {
+ args.putParcelable(ARG_DEVICE, device);
args.putString(ARG_ACCESSORY_NAME, deviceName);
args.putInt(ARG_ACCESSORY_ICON_ID, deviceImgId);
}
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ mDevice = getArguments().getParcelable(ARG_DEVICE);
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (mDevice.getBondState() == BluetoothDevice.BOND_NONE) {
+ navigateBack();
+ }
+ final IntentFilter adapterIntentFilter = new IntentFilter();
+ adapterIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
+ mBroadcastReceiver = new UnpairReceiver(this, mDevice);
+ getActivity().registerReceiver(mBroadcastReceiver, adapterIntentFilter);
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ getActivity().unregisterReceiver(mBroadcastReceiver);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mHandler.removeCallbacks(mTimeoutRunnable);
+ mHandler.removeCallbacks(mBailoutRunnable);
+ }
+
@NonNull
@Override
public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
@@ -364,14 +403,45 @@
@Override
public void onGuidedActionClicked(GuidedAction action) {
if (action.getId() == GuidedAction.ACTION_ID_OK) {
- final BluetoothAccessoryFragment fragment =
- (BluetoothAccessoryFragment) getTargetFragment();
- fragment.unpairDevice();
+ unpairDevice();
} else if (action.getId() == GuidedAction.ACTION_ID_CANCEL) {
getFragmentManager().popBackStack();
} else {
super.onGuidedActionClicked(action);
}
}
+
+ private void navigateBack() {
+ // need to post this to avoid recursing in the fragment manager.
+ mHandler.removeCallbacks(mBailoutRunnable);
+ mHandler.post(mBailoutRunnable);
+ }
+
+ private void unpairDevice() {
+ if (mDevice != null) {
+ int state = mDevice.getBondState();
+
+ if (state == BluetoothDevice.BOND_BONDING) {
+ mDevice.cancelBondProcess();
+ }
+
+ if (state != BluetoothDevice.BOND_NONE) {
+ ((BluetoothAccessoryFragment) getTargetFragment()).setUnpairing(true);
+ // Set a timeout, just in case we don't receive the unpair notification we
+ // use to finish the activity
+ mHandler.postDelayed(mTimeoutRunnable, UNPAIR_TIMEOUT);
+ final boolean successful = mDevice.removeBond();
+ if (successful) {
+ if (DEBUG) {
+ Log.d(TAG, "Bluetooth device successfully unpaired.");
+ }
+ } else {
+ Log.e(TAG, "Failed to unpair Bluetooth Device: " + mDevice.getName());
+ }
+ }
+ } else {
+ Log.e(TAG, "Bluetooth device not found. Address = " + mDevice.getAddress());
+ }
+ }
}
}
diff --git a/Settings/src/com/android/tv/settings/connectivity/WpsConnectionActivity.java b/Settings/src/com/android/tv/settings/connectivity/WpsConnectionActivity.java
index ea089aa..840c992 100644
--- a/Settings/src/com/android/tv/settings/connectivity/WpsConnectionActivity.java
+++ b/Settings/src/com/android/tv/settings/connectivity/WpsConnectionActivity.java
@@ -99,6 +99,10 @@
setLayoutProperties(R.layout.setup_auth_activity, R.id.description, R.id.action);
super.onCreate(savedInstanceState);
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+
+ if (ThemeHelper.fromSetupWizard(getIntent())) {
+ setTitle(getResources().getString(R.string.wifi_wps_title));
+ }
}
@Override
diff --git a/Settings/src/com/android/tv/settings/connectivity/setup/WifiSetupActivity.java b/Settings/src/com/android/tv/settings/connectivity/setup/WifiSetupActivity.java
index ccad5e1..38f864c 100644
--- a/Settings/src/com/android/tv/settings/connectivity/setup/WifiSetupActivity.java
+++ b/Settings/src/com/android/tv/settings/connectivity/setup/WifiSetupActivity.java
@@ -34,6 +34,7 @@
import android.os.Message;
import android.text.TextUtils;
import android.util.Pair;
+import android.view.accessibility.AccessibilityEvent;
import com.android.settingslib.wifi.WifiTracker;
import com.android.tv.settings.R;
@@ -382,6 +383,9 @@
mWifiTracker.resumeScanning();
}
}
+ if (ThemeHelper.fromSetupWizard(getIntent())) {
+ updateTitle(formPageType);
+ }
}
@Override
@@ -532,4 +536,32 @@
addPage(WifiFormPageType.SUMMARY_NOT_CONNECTED);
}
}
+
+ private void updateTitle(WifiFormPageType pageType) {
+ switch (pageType) {
+ // Fall through for all pageTypes that require the SSID of the network for
+ // the title.
+ case ADVANCED_OPTIONS:
+ case CONNECT:
+ case CONNECT_FAILED:
+ case CONNECT_TIMEOUT:
+ case ENTER_PASSWORD:
+ case KNOWN_NETWORK:
+ case SAVE:
+ case SAVE_FAILED:
+ setTitle(getResources().getString(pageType.getTitleResourceId(),
+ mConfiguration.getPrintableSsid()));
+ break;
+ case WPS:
+ // Delegate title to the WPSConnectionActivity. Use blank string to prevent
+ // talkback from announcing a misplaced title.
+ setTitle("");
+ return;
+ default:
+ setTitle(getResources().getString(pageType.getTitleResourceId()));
+ break;
+ }
+ getWindow().getDecorView()
+ .sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
}