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