1 /* 2 * Copyright (C) 2021 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 android.permissionui.cts.usepermission 17 18 import android.bluetooth.BluetoothManager 19 import android.bluetooth.le.BluetoothLeScanner 20 import android.bluetooth.le.ScanCallback 21 import android.bluetooth.le.ScanResult 22 import android.content.ContentProvider 23 import android.content.ContentValues 24 import android.content.Intent 25 import android.database.Cursor 26 import android.net.Uri 27 import android.os.Bundle 28 import android.os.SystemClock 29 import android.util.Base64 30 import android.util.Log 31 import java.util.concurrent.ConcurrentHashMap 32 import java.util.concurrent.atomic.AtomicInteger 33 34 private const val LOG_TAG = "AccessBluetoothOnCommand" 35 36 class AccessBluetoothOnCommand : ContentProvider() { 37 38 private enum class Result { 39 UNKNOWN, 40 ERROR, 41 EXCEPTION, 42 EMPTY, 43 FILTERED, 44 FULL 45 } 46 callnull47 override fun call(authority: String, method: String, arg: String?, extras: Bundle?): Bundle? { 48 Log.v(LOG_TAG, "call() - start") 49 val res = Bundle() 50 51 var scanner: BluetoothLeScanner? = null 52 var scanCallback: ScanCallback? = null 53 54 try { 55 56 scanner = 57 context!! 58 .getSystemService(BluetoothManager::class.java) 59 ?.adapter!! 60 .bluetoothLeScanner 61 62 val observedScans: MutableSet<String> = ConcurrentHashMap.newKeySet() 63 val observedErrorCode = AtomicInteger(0) 64 65 scanCallback = 66 object : ScanCallback() { 67 override fun onScanResult(callbackType: Int, result: ScanResult) { 68 Log.v(LOG_TAG, "onScanResult() - result = $result") 69 observedScans.add(Base64.encodeToString(result.scanRecord!!.bytes, 0)) 70 } 71 72 override fun onBatchScanResults(results: List<ScanResult>) { 73 Log.v(LOG_TAG, "onBatchScanResults() - results.size = ${results.size}") 74 for (result in results) { 75 onScanResult(0, result) 76 } 77 } 78 79 override fun onScanFailed(errorCode: Int) { 80 Log.e(LOG_TAG, "onScanFailed() - errorCode = $errorCode") 81 observedErrorCode.set(errorCode) 82 } 83 } 84 85 Log.v(LOG_TAG, "call() - startScan...") 86 scanner.startScan(scanCallback) 87 88 // Wait a few seconds to figure out what we actually observed 89 Log.v(LOG_TAG, "call() - sleep...") 90 SystemClock.sleep(3000) 91 92 if (observedErrorCode.get() > 0) { 93 Log.v(LOG_TAG, "call() observed error: ${observedErrorCode.get()}") 94 res.putInt(Intent.EXTRA_INDEX, Result.ERROR.ordinal) 95 return res 96 } 97 Log.v(LOG_TAG, "call() - (scanCount=${observedScans.size})") 98 99 when (observedScans.size) { 100 0 -> res.putInt(Intent.EXTRA_INDEX, Result.EMPTY.ordinal) 101 1 -> res.putInt(Intent.EXTRA_INDEX, Result.FILTERED.ordinal) 102 5 -> res.putInt(Intent.EXTRA_INDEX, Result.FULL.ordinal) 103 else -> res.putInt(Intent.EXTRA_INDEX, Result.UNKNOWN.ordinal) 104 } 105 } catch (t: Throwable) { 106 Log.e(LOG_TAG, "call() - EXCEPTION", t) 107 res.putInt(Intent.EXTRA_INDEX, Result.EXCEPTION.ordinal) 108 } finally { 109 try { 110 Log.v(LOG_TAG, "call() - finally - stopScan...") 111 scanner!!.stopScan(scanCallback) 112 } catch (e: Exception) { 113 Log.e(LOG_TAG, "call() - finally - EXCEPTION", e) 114 } 115 } 116 Log.v(LOG_TAG, "call() - end") 117 return res 118 } 119 onCreatenull120 override fun onCreate(): Boolean { 121 return true 122 } 123 querynull124 override fun query( 125 uri: Uri, 126 projection: Array<String>?, 127 selection: String?, 128 selectionArgs: Array<String>?, 129 sortOrder: String? 130 ): Cursor? { 131 throw UnsupportedOperationException() 132 } 133 getTypenull134 override fun getType(uri: Uri): String? { 135 throw UnsupportedOperationException() 136 } 137 insertnull138 override fun insert(uri: Uri, values: ContentValues?): Uri? { 139 throw UnsupportedOperationException() 140 } 141 deletenull142 override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int { 143 throw UnsupportedOperationException() 144 } 145 updatenull146 override fun update( 147 uri: Uri, 148 values: ContentValues?, 149 selection: String?, 150 selectionArgs: Array<String>? 151 ): Int { 152 throw UnsupportedOperationException() 153 } 154 } 155