1 /*
2  * Copyright (C) 2018 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 
17 package com.android.tv.settings.accessories;
18 
19 import android.bluetooth.BluetoothAdapter;
20 import android.bluetooth.BluetoothDevice;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.os.Bundle;
26 import android.text.TextUtils;
27 import android.util.ArraySet;
28 import android.util.Log;
29 
30 import androidx.annotation.Keep;
31 import androidx.preference.Preference;
32 import androidx.preference.PreferenceScreen;
33 
34 import com.android.internal.logging.nano.MetricsProto;
35 import com.android.tv.settings.R;
36 import com.android.tv.settings.SettingsPreferenceFragment;
37 
38 import java.util.Set;
39 
40 /**
41  * The "Remotes and Accessories" screen in TV settings.
42  */
43 @Keep
44 public class AccessoriesFragment extends SettingsPreferenceFragment {
45     private static final String TAG = "AccessoriesFragment";
46     private static final String KEY_ADD_ACCESSORY = "add_accessory";
47 
48     private BluetoothAdapter mBtAdapter;
49     private Preference mAddAccessory;
50     private final BroadcastReceiver mBCMReceiver = new BroadcastReceiver() {
51         @Override
52         public void onReceive(Context context, Intent intent) {
53             updateAccessories();
54         }
55     };
56 
57     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)58     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
59         setPreferencesFromResource(R.xml.remotes_and_accessories, null);
60         mAddAccessory = findPreference(KEY_ADD_ACCESSORY);
61     }
62 
63     @Override
getMetricsCategory()64     public int getMetricsCategory() {
65         return  MetricsProto.MetricsEvent.BLUETOOTH;
66     }
67 
updateAccessories()68     private void updateAccessories() {
69         PreferenceScreen preferenceScreen = getPreferenceScreen();
70         if (preferenceScreen == null) {
71             return;
72         }
73 
74         if (mBtAdapter == null) {
75             preferenceScreen.removeAll();
76             return;
77         }
78 
79         final Set<BluetoothDevice> bondedDevices = mBtAdapter.getBondedDevices();
80         if (bondedDevices == null) {
81             preferenceScreen.removeAll();
82             return;
83         }
84 
85         final Context themedContext = getPreferenceManager().getContext();
86 
87         final Set<String> touchedKeys = new ArraySet<>(bondedDevices.size() + 1);
88         if (mAddAccessory != null) {
89             touchedKeys.add(mAddAccessory.getKey());
90         }
91 
92         for (final BluetoothDevice device : bondedDevices) {
93             final String deviceAddress = device.getAddress();
94             if (TextUtils.isEmpty(deviceAddress)) {
95                 Log.w(TAG, "Skipping mysteriously empty bluetooth device");
96                 continue;
97             }
98 
99             final String desc = device.isConnected() ? getString(R.string.accessory_connected) :
100                     null;
101             final String key = "BluetoothDevice:" + deviceAddress;
102             touchedKeys.add(key);
103             Preference preference = preferenceScreen.findPreference(key);
104             if (preference == null) {
105                 preference = new Preference(themedContext);
106                 preference.setKey(key);
107             }
108             final String deviceName = device.getAlias();
109             preference.setTitle(deviceName);
110             preference.setSummary(desc);
111             final int deviceImgId = AccessoryUtils.getImageIdForDevice(device);
112             preference.setIcon(deviceImgId);
113             preference.setFragment(BluetoothAccessoryFragment.class.getName());
114             BluetoothAccessoryFragment.prepareArgs(
115                     preference.getExtras(),
116                     deviceAddress,
117                     deviceName,
118                     deviceImgId);
119             preferenceScreen.addPreference(preference);
120         }
121 
122         for (int i = 0; i < preferenceScreen.getPreferenceCount();) {
123             final Preference preference = preferenceScreen.getPreference(i);
124             if (touchedKeys.contains(preference.getKey())) {
125                 i++;
126             } else {
127                 preferenceScreen.removePreference(preference);
128             }
129         }
130     }
131 
132     @Override
onStart()133     public void onStart() {
134         super.onStart();
135         IntentFilter btChangeFilter = new IntentFilter();
136         btChangeFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
137         btChangeFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
138         btChangeFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
139         getContext().registerReceiver(mBCMReceiver, btChangeFilter);
140     }
141 
142     @Override
onStop()143     public void onStop() {
144         super.onStop();
145         getContext().unregisterReceiver(mBCMReceiver);
146     }
147 
148     @Override
onResume()149     public void onResume() {
150         super.onResume();
151         updateAccessories();
152     }
153 
154     @Override
onCreate(Bundle savedInstanceState)155     public void onCreate(Bundle savedInstanceState) {
156         mBtAdapter = BluetoothAdapter.getDefaultAdapter();
157         super.onCreate(savedInstanceState);
158     }
159 }
160