1 /* 2 * Copyright 2023 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.bluetooth.btservice; 18 19 import android.bluetooth.BluetoothAdapter; 20 import android.bluetooth.BluetoothClass; 21 import android.bluetooth.BluetoothDevice; 22 import android.bluetooth.BluetoothQualityReport; 23 import android.bluetooth.BluetoothStatusCodes; 24 import android.util.Log; 25 26 import com.android.bluetooth.Utils; 27 import com.android.internal.annotations.GuardedBy; 28 import com.android.internal.annotations.VisibleForTesting; 29 30 /** Native interface to BQR */ 31 public class BluetoothQualityReportNativeInterface { 32 private static final String TAG = "BluetoothQualityReportNativeInterface"; 33 34 @GuardedBy("INSTANCE_LOCK") 35 private static BluetoothQualityReportNativeInterface sInstance; 36 37 private static final Object INSTANCE_LOCK = new Object(); 38 BluetoothQualityReportNativeInterface()39 private BluetoothQualityReportNativeInterface() {} 40 41 /** Get singleton instance. */ getInstance()42 public static BluetoothQualityReportNativeInterface getInstance() { 43 synchronized (INSTANCE_LOCK) { 44 if (sInstance == null) { 45 sInstance = new BluetoothQualityReportNativeInterface(); 46 } 47 return sInstance; 48 } 49 } 50 51 /** Set singleton instance. */ 52 @VisibleForTesting setInstance(BluetoothQualityReportNativeInterface instance)53 static void setInstance(BluetoothQualityReportNativeInterface instance) { 54 synchronized (INSTANCE_LOCK) { 55 sInstance = instance; 56 } 57 } 58 59 /** 60 * Initializes the native interface. 61 * 62 * <p>priorities to configure. 63 */ init()64 public void init() { 65 initNative(); 66 } 67 68 /** Cleanup the native interface. */ cleanup()69 public void cleanup() { 70 cleanupNative(); 71 } 72 73 /** Callback from the native stack back into the Java framework. */ bqrDeliver( byte[] remoteAddr, int lmpVer, int lmpSubVer, int manufacturerId, byte[] bqrRawData)74 private void bqrDeliver( 75 byte[] remoteAddr, int lmpVer, int lmpSubVer, int manufacturerId, byte[] bqrRawData) { 76 BluetoothClass remoteBtClass = null; 77 BluetoothDevice device = null; 78 String remoteName = null; 79 80 String remoteAddress = Utils.getAddressStringFromByte(remoteAddr); 81 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 82 83 if (remoteAddress != null && adapter != null) { 84 device = adapter.getRemoteDevice(remoteAddress); 85 if (device == null) { 86 Log.e(TAG, "bqrDeliver failed: device is null"); 87 return; 88 } 89 remoteName = device.getName(); 90 remoteBtClass = device.getBluetoothClass(); 91 } else { 92 Log.e( 93 TAG, 94 "bqrDeliver failed: " 95 + (remoteAddress == null 96 ? "remoteAddress is null" 97 : "adapter is null")); 98 return; 99 } 100 101 BluetoothQualityReport bqr; 102 try { 103 bqr = 104 new BluetoothQualityReport.Builder(bqrRawData) 105 .setRemoteAddress(remoteAddress) 106 .setLmpVersion(lmpVer) 107 .setLmpSubVersion(lmpSubVer) 108 .setManufacturerId(manufacturerId) 109 .setRemoteName(remoteName) 110 .setBluetoothClass(remoteBtClass) 111 .build(); 112 Log.i(TAG, bqr.toString()); 113 } catch (Exception e) { 114 Log.e(TAG, "bqrDeliver failed: failed to create BluetotQualityReport", e); 115 return; 116 } 117 118 try { 119 AdapterService adapterService = AdapterService.getAdapterService(); 120 if (adapterService == null) { 121 Log.e(TAG, "bqrDeliver failed: adapterService is null"); 122 return; 123 } 124 int status = adapterService.bluetoothQualityReportReadyCallback(device, bqr); 125 if (status != BluetoothStatusCodes.SUCCESS) { 126 Log.e(TAG, "bluetoothQualityReportReadyCallback failed, status: " + status); 127 } 128 } catch (Exception e) { 129 Log.e(TAG, "bqrDeliver failed: bluetoothQualityReportReadyCallback error", e); 130 return; 131 } 132 } 133 134 // Native methods that call into the JNI interface initNative()135 private native void initNative(); 136 cleanupNative()137 private native void cleanupNative(); 138 } 139