1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.car.settings.bluetooth;
17 
18 import android.bluetooth.BluetoothDevice;
19 import android.os.Bundle;
20 import android.support.car.ui.PagedListView;
21 import android.text.Editable;
22 import android.text.TextWatcher;
23 import android.util.Log;
24 import android.view.View;
25 import android.widget.Button;
26 import android.widget.EditText;
27 
28 import com.android.car.settings.common.CarSettingActivity;
29 import com.android.car.settings.R;
30 import com.android.car.settings.common.NoDividerItemDecoration;
31 import com.android.car.settings.common.TypedPagedListAdapter;
32 
33 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
34 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
35 import com.android.settingslib.bluetooth.LocalBluetoothManager;
36 import com.android.settingslib.bluetooth.LocalBluetoothProfile;
37 import com.android.settingslib.bluetooth.MapProfile;
38 import com.android.settingslib.bluetooth.PanProfile;
39 import com.android.settingslib.bluetooth.PbapServerProfile;
40 
41 import java.util.ArrayList;
42 
43 /**
44  * Shows details about a bluetooth device, including actions related to the device,
45  * e.g. forget etc. The intent should include information about the device, use that to
46  * render UI, e.g. show name etc.
47  */
48 public class BluetoothDetailActivity extends CarSettingActivity implements
49         BluetoothProfileLineItem.DataChangedListener {
50     private static final String TAG = "BluetoothDetailActivity";
51     public static final String BT_DEVICE_KEY = "btDeviceKey";
52 
53     private BluetoothDevice mDevice;
54     private CachedBluetoothDevice mCachedDevice;
55     private PagedListView mListView;
56     private TypedPagedListAdapter mPagedListAdapter;
57     private LocalBluetoothManager mLocalManager;
58     private CachedBluetoothDeviceManager mDeviceManager;
59     private EditText mNameView;
60     private Button mOkButton;
61 
62     @Override
onCreate(Bundle savedInstanceState)63     protected void onCreate(Bundle savedInstanceState) {
64         super.onCreate(savedInstanceState);
65         setContentView(R.layout.bluetooth_details);
66         mListView = (PagedListView) findViewById(R.id.list);
67         mListView.setDefaultItemDecoration(new NoDividerItemDecoration(this));
68         mListView.setDarkMode();
69 
70         if (getIntent() != null && getIntent().getExtras() != null) {
71             mDevice = getIntent().getExtras().getParcelable(BT_DEVICE_KEY);
72         }
73         if (mDevice == null) {
74             Log.w(TAG, "No bluetooth device set.");
75             return;
76         }
77 
78         mLocalManager = LocalBluetoothManager.getInstance(this /* context */ , null /* listener */);
79         if (mLocalManager == null) {
80             Log.e(TAG, "Bluetooth is not supported on this device");
81             return;
82         }
83         mDeviceManager = mLocalManager.getCachedDeviceManager();
84         mCachedDevice = mDeviceManager.findDevice(mDevice);
85         if (mCachedDevice == null) {
86             mCachedDevice = mDeviceManager.addDevice(
87                     mLocalManager.getBluetoothAdapter(),
88                     mLocalManager.getProfileManager(),
89                     mDevice);
90         }
91 
92         mNameView = (EditText) findViewById(R.id.bt_name);
93         mNameView.setText(mDevice.getName());
94         setupForgetButton();
95         setupOkButton();
96 
97         mPagedListAdapter = new TypedPagedListAdapter(this /* context */, getProfileLineItems());
98         mListView.setAdapter(mPagedListAdapter);
99     }
100 
101     @Override
setupActionBar()102     public void setupActionBar() {
103         super.setupActionBar();
104         getActionBar().setCustomView(R.layout.action_bar_with_button);
105         getActionBar().setDisplayShowCustomEnabled(true);
106     }
107 
108     @Override
onDataChanged()109     public void onDataChanged() {
110         mPagedListAdapter.notifyDataSetChanged();
111     }
112 
getProfileLineItems()113     private ArrayList<TypedPagedListAdapter.LineItem> getProfileLineItems() {
114         ArrayList<TypedPagedListAdapter.LineItem> lineItems = new ArrayList<>();
115         for (LocalBluetoothProfile profile : mCachedDevice.getConnectableProfiles()) {
116             lineItems.add(new BluetoothProfileLineItem(
117                     this /* context */, profile, mCachedDevice, this));
118         }
119 
120         int pbapPermission = mCachedDevice.getPhonebookPermissionChoice();
121         // Only provide PBAP cabability if the client device has requested PBAP.
122         if (pbapPermission != CachedBluetoothDevice.ACCESS_UNKNOWN) {
123             PbapServerProfile psp = mLocalManager.getProfileManager().getPbapProfile();
124             lineItems.add(new BluetoothProfileLineItem(
125                     this /* context */, psp, mCachedDevice, this));
126         }
127 
128         int mapPermission = mCachedDevice.getMessagePermissionChoice();
129         if (mapPermission != CachedBluetoothDevice.ACCESS_UNKNOWN) {
130             MapProfile mapProfile = mLocalManager.getProfileManager().getMapProfile();
131             lineItems.add(new BluetoothProfileLineItem(
132                     this /* context */, mapProfile, mCachedDevice, this));
133         }
134         return lineItems;
135     }
136 
setupForgetButton()137     private void setupForgetButton() {
138         Button fortgetButton = (Button) findViewById(R.id.action_button2);
139         fortgetButton.setVisibility(View.VISIBLE);
140         fortgetButton.setText(R.string.forget);
141         fortgetButton.setOnClickListener(v -> {
142             mCachedDevice.unpair();
143             finish();
144         });
145     }
146 
setupOkButton()147     private void setupOkButton() {
148         mOkButton = (Button) findViewById(R.id.action_button1);
149         mOkButton.setText(R.string.okay);
150         // before the text gets changed, always set it in a disabled state.
151         mOkButton.setEnabled(false);
152         mNameView.addTextChangedListener(new TextWatcher() {
153             @Override
154             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
155                 // don't care
156             }
157 
158             @Override
159             public void onTextChanged(CharSequence s, int start, int before, int count) {
160                 // dont' care
161             }
162 
163             @Override
164             public void afterTextChanged(Editable s) {
165                 mOkButton.setEnabled(!s.toString().equals(mDevice.getName()));
166             }
167         });
168         mOkButton.setOnClickListener(v -> {
169             mCachedDevice.setName(mNameView.getText().toString());
170             finish();
171         });
172     }
173 }
174