1 /*
2  * Copyright (C) 2016 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.cts.verifier.bluetooth;
18 
19 import android.app.AlertDialog;
20 import android.app.Dialog;
21 import android.app.ProgressDialog;
22 import android.bluetooth.BluetoothAdapter;
23 import android.bluetooth.BluetoothManager;
24 import android.content.BroadcastReceiver;
25 import android.content.Context;
26 import android.content.DialogInterface;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.os.Bundle;
30 import android.os.Handler;
31 import android.util.Log;
32 import android.view.View;
33 import android.widget.AdapterView;
34 import android.widget.ListView;
35 
36 import com.android.cts.verifier.PassFailButtons;
37 import com.android.cts.verifier.R;
38 
39 import java.util.ArrayList;
40 import java.util.List;
41 
42 public class BleEncryptedClientBaseActivity extends PassFailButtons.Activity {
43 
44     private TestAdapter mTestAdapter;
45     private int mAllPassed;
46     private Dialog mDialog;
47     private Handler mHandler;
48 
49     private final int BLE_WRITE_ENCRIPTED_CHARACTERISTIC = 0;
50     private final int BLE_READ_ENCRIPTED_CHARACTERISTIC = 1;
51     private final int BLE_WRITE_ENCRIPTED_DESCRIPTOR = 2;
52     private final int BLE_READ_ENCRIPTED_DESCRIPTOR = 3;
53 
54     @Override
onCreate(Bundle savedInstanceState)55     protected void onCreate(Bundle savedInstanceState) {
56         super.onCreate(savedInstanceState);
57         setContentView(R.layout.ble_encrypted_client_test);
58         setPassFailButtonClickListeners();
59         setInfoResources(R.string.ble_encrypted_client_name,
60                 R.string.ble_encrypted_client_info, -1);
61         getPassButton().setEnabled(false);
62 
63         mHandler = new Handler();
64 
65         mTestAdapter = new TestAdapter(this, setupTestList());
66         ListView listView = (ListView) findViewById(R.id.ble_client_enctypted_tests);
67         listView.setAdapter(mTestAdapter);
68         listView.setOnItemClickListener(new ListView.OnItemClickListener() {
69             @Override
70             public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
71                 Intent intent = new Intent(BleEncryptedClientBaseActivity.this, BleEncryptedClientService.class);
72                 Log.v(getLocalClassName(), "onItemClick()");
73                 switch (position) {
74                 case BLE_WRITE_ENCRIPTED_CHARACTERISTIC:
75                     intent.setAction(BleEncryptedClientService.ACTION_WRITE_ENCRYPTED_CHARACTERISTIC);
76                     break;
77                 case BLE_READ_ENCRIPTED_CHARACTERISTIC:
78                     intent.setAction(BleEncryptedClientService.ACTION_READ_ENCRYPTED_CHARACTERISTIC);
79                     break;
80                 case BLE_WRITE_ENCRIPTED_DESCRIPTOR:
81                     intent.setAction(BleEncryptedClientService.ACTION_WRITE_ENCRYPTED_DESCRIPTOR);
82                     break;
83                 case BLE_READ_ENCRIPTED_DESCRIPTOR:
84                     intent.setAction(BleEncryptedClientService.ACTION_READ_ENCRYPTED_DESCRIPTOR);
85                     break;
86                 default:
87                     return;
88                 }
89                 startService(intent);
90                 showProgressDialog();
91             }
92         });
93 
94         mAllPassed = 0;
95     }
96 
97     @Override
onResume()98     public void onResume() {
99         super.onResume();
100 
101         IntentFilter filter = new IntentFilter();
102         filter.addAction(BleEncryptedClientService.INTENT_BLE_BLUETOOTH_DISABLED);
103         filter.addAction(BleEncryptedClientService.INTENT_BLE_WRITE_ENCRYPTED_CHARACTERISTIC);
104         filter.addAction(BleEncryptedClientService.INTENT_BLE_READ_ENCRYPTED_CHARACTERISTIC);
105         filter.addAction(BleEncryptedClientService.INTENT_BLE_WRITE_ENCRYPTED_DESCRIPTOR);
106         filter.addAction(BleEncryptedClientService.INTENT_BLE_READ_ENCRYPTED_DESCRIPTOR);
107         filter.addAction(BleEncryptedClientService.INTENT_BLE_WRITE_NOT_ENCRYPTED_CHARACTERISTIC);
108         filter.addAction(BleEncryptedClientService.INTENT_BLE_READ_NOT_ENCRYPTED_CHARACTERISTIC);
109         filter.addAction(BleEncryptedClientService.INTENT_BLE_WRITE_NOT_ENCRYPTED_DESCRIPTOR);
110         filter.addAction(BleEncryptedClientService.INTENT_BLE_READ_NOT_ENCRYPTED_DESCRIPTOR);
111         filter.addAction(BleEncryptedClientService.INTENT_BLE_WRITE_FAIL_ENCRYPTED_CHARACTERISTIC);
112         filter.addAction(BleEncryptedClientService.INTENT_BLE_READ_FAIL_ENCRYPTED_CHARACTERISTIC);
113         filter.addAction(BleEncryptedClientService.INTENT_BLE_WRITE_FAIL_ENCRYPTED_DESCRIPTOR);
114         filter.addAction(BleEncryptedClientService.INTENT_BLE_READ_FAIL_ENCRYPTED_DESCRIPTOR);
115         filter.addAction(BleEncryptedClientService.ACTION_DISCONNECTED);
116         registerReceiver(mBroadcast, filter);
117     }
118 
119     @Override
onPause()120     public void onPause() {
121         super.onPause();
122         unregisterReceiver(mBroadcast);
123         closeDialog();
124     }
125 
setupTestList()126     private List<Integer> setupTestList() {
127         ArrayList<Integer> testList = new ArrayList<Integer>();
128         testList.add(R.string.ble_write_authenticated_characteristic_name);
129         testList.add(R.string.ble_read_authenticated_characteristic_name);
130         testList.add(R.string.ble_write_authenticated_descriptor_name);
131         testList.add(R.string.ble_read_authenticated_descriptor_name);
132         return testList;
133     }
134 
showErrorDialog(String title, String message, boolean finish)135     private void showErrorDialog(String title, String message, boolean finish) {
136         closeDialog();
137 
138         AlertDialog.Builder builder = new AlertDialog.Builder(this)
139                 .setTitle(title)
140                 .setMessage(message);
141         if (finish) {
142             builder.setOnCancelListener(new Dialog.OnCancelListener() {
143                 @Override
144                 public void onCancel(DialogInterface dialog) {
145                     finish();
146                 }
147             });
148         }
149         builder.create().show();
150     }
151 
closeDialog()152     private synchronized void closeDialog() {
153         if (mDialog != null) {
154             mDialog.dismiss();
155             mDialog = null;
156         }
157     }
158 
showProgressDialog()159     private synchronized void showProgressDialog() {
160         closeDialog();
161 
162         ProgressDialog dialog = new ProgressDialog(this);
163         dialog.setTitle(R.string.ble_test_running);
164         dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
165         dialog.setMessage(getString(R.string.ble_test_running_message));
166         dialog.setCanceledOnTouchOutside(false);
167         mDialog = dialog;
168         mDialog.show();
169     }
170 
shouldRebootBluetoothAfterTest()171     public boolean shouldRebootBluetoothAfterTest() {
172         return false;
173     }
174 
isSecure()175     public boolean isSecure() { return false; }
176 
177     private BroadcastReceiver mBroadcast = new BroadcastReceiver() {
178         @Override
179         public void onReceive(Context context, Intent intent) {
180             String action = intent.getAction();
181             switch (action) {
182             case BleEncryptedClientService.INTENT_BLE_BLUETOOTH_DISABLED:
183                 showErrorDialog(getString(R.string.ble_bluetooth_disable_title), getString(R.string.ble_bluetooth_disable_message), true);
184                 break;
185             case BleEncryptedClientService.INTENT_BLE_WRITE_ENCRYPTED_CHARACTERISTIC:
186                 mTestAdapter.setTestPass(BLE_WRITE_ENCRIPTED_CHARACTERISTIC);
187                 mAllPassed |= 0x01;
188                 if (!isSecure()) {
189                     closeDialog();
190                 }
191                 break;
192             case BleEncryptedClientService.INTENT_BLE_READ_ENCRYPTED_CHARACTERISTIC:
193                 mTestAdapter.setTestPass(BLE_READ_ENCRIPTED_CHARACTERISTIC);
194                 mAllPassed |= 0x02;
195                 if (!isSecure()) {
196                     closeDialog();
197                 }
198                 break;
199             case BleEncryptedClientService.INTENT_BLE_WRITE_ENCRYPTED_DESCRIPTOR:
200                 mTestAdapter.setTestPass(BLE_WRITE_ENCRIPTED_DESCRIPTOR);
201                 mAllPassed |= 0x04;
202                 if (!isSecure()) {
203                     closeDialog();
204                 }
205                 break;
206             case BleEncryptedClientService.INTENT_BLE_READ_ENCRYPTED_DESCRIPTOR:
207                 mTestAdapter.setTestPass(BLE_READ_ENCRIPTED_DESCRIPTOR);
208                 mAllPassed |= 0x08;
209                 if (!isSecure()) {
210                     closeDialog();
211                 }
212                 break;
213             case BleEncryptedClientService.INTENT_BLE_WRITE_NOT_ENCRYPTED_CHARACTERISTIC:
214                 showErrorDialog(getString(R.string.ble_encrypted_client_name), getString(R.string.ble_encrypted_client_no_encrypted_characteristic), false);
215                 break;
216             case BleEncryptedClientService.INTENT_BLE_READ_NOT_ENCRYPTED_CHARACTERISTIC:
217                 showErrorDialog(getString(R.string.ble_encrypted_client_name), getString(R.string.ble_encrypted_client_no_encrypted_characteristic), false);
218                 break;
219             case BleEncryptedClientService.INTENT_BLE_WRITE_NOT_ENCRYPTED_DESCRIPTOR:
220                 showErrorDialog(getString(R.string.ble_encrypted_client_name), getString(R.string.ble_encrypted_client_no_encrypted_descriptor), false);
221                 break;
222             case BleEncryptedClientService.INTENT_BLE_READ_NOT_ENCRYPTED_DESCRIPTOR:
223                 showErrorDialog(getString(R.string.ble_encrypted_client_name), getString(R.string.ble_encrypted_client_no_encrypted_descriptor), false);
224                 break;
225 
226             case BleEncryptedClientService.INTENT_BLE_WRITE_FAIL_ENCRYPTED_CHARACTERISTIC:
227                 showErrorDialog(getString(R.string.ble_encrypted_client_name), getString(R.string.ble_encrypted_client_fail_write_encrypted_characteristic), false);
228                 break;
229             case BleEncryptedClientService.INTENT_BLE_READ_FAIL_ENCRYPTED_CHARACTERISTIC:
230                 showErrorDialog(getString(R.string.ble_encrypted_client_name), getString(R.string.ble_encrypted_client_fail_read_encrypted_characteristic), false);
231                 break;
232             case BleEncryptedClientService.INTENT_BLE_WRITE_FAIL_ENCRYPTED_DESCRIPTOR:
233                 showErrorDialog(getString(R.string.ble_encrypted_client_name), getString(R.string.ble_encrypted_client_fail_write_encrypted_descriptor), false);
234                 break;
235             case BleEncryptedClientService.INTENT_BLE_READ_FAIL_ENCRYPTED_DESCRIPTOR:
236                 showErrorDialog(getString(R.string.ble_encrypted_client_name), getString(R.string.ble_encrypted_client_fail_read_encrypted_descriptor), false);
237                 break;
238 
239             case BleEncryptedClientService.ACTION_DISCONNECTED:
240                 if (shouldRebootBluetoothAfterTest()) {
241                     mBtPowerSwitcher.executeSwitching();
242                 } else {
243                     closeDialog();
244                 }
245                 break;
246             }
247 
248             mTestAdapter.notifyDataSetChanged();
249             if (mAllPassed == 0x0F) {
250                 getPassButton().setEnabled(true);
251             }
252         }
253     };
254 
255     private static final long BT_ON_DELAY = 10000;
256     private final BluetoothPowerSwitcher mBtPowerSwitcher = new BluetoothPowerSwitcher();
257     private class BluetoothPowerSwitcher extends BroadcastReceiver {
258 
259         private boolean mIsSwitching = false;
260         private BluetoothAdapter mAdapter;
261 
executeSwitching()262         public void executeSwitching() {
263             if (mAdapter == null) {
264                 BluetoothManager btMgr = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
265                 mAdapter = btMgr.getAdapter();
266             }
267 
268             if (!mIsSwitching) {
269                 IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
270                 registerReceiver(this, filter);
271                 mIsSwitching = true;
272                 mHandler.postDelayed(new Runnable() {
273                     @Override
274                     public void run() {
275                         mAdapter.disable();
276                     }
277                 }, 1000);
278             }
279         }
280 
281         @Override
onReceive(Context context, Intent intent)282         public void onReceive(Context context, Intent intent) {
283             if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
284                 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
285                 if (state == BluetoothAdapter.STATE_OFF) {
286                     mHandler.postDelayed(new Runnable() {
287                         @Override
288                         public void run() {
289                             mAdapter.enable();
290                         }
291                     }, BT_ON_DELAY);
292                 } else if (state == BluetoothAdapter.STATE_ON) {
293                     mIsSwitching = false;
294                     unregisterReceiver(this);
295                     getPassButton().setEnabled(true);
296                     closeDialog();
297                 }
298             }
299         }
300     }
301 }
302