1 /* <lambda>null2 * Copyright (C) 2025 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.gatt 18 19 import android.Manifest.permission.BLUETOOTH_ADVERTISE 20 import android.Manifest.permission.BLUETOOTH_PRIVILEGED 21 import android.annotation.RequiresPermission 22 import android.bluetooth.IBluetoothAdvertise 23 import android.bluetooth.le.AdvertiseData 24 import android.bluetooth.le.AdvertisingSetParameters 25 import android.bluetooth.le.IAdvertisingSetCallback 26 import android.bluetooth.le.PeriodicAdvertisingParameters 27 import android.content.AttributionSource 28 import android.content.Context 29 import com.android.bluetooth.Utils 30 31 class AdvertiseBinder( 32 private val mContext: Context, 33 private val mAdvertiseManager: AdvertiseManager, 34 ) : IBluetoothAdvertise.Stub() { 35 @Volatile private var mIsAvailable = true 36 37 fun cleanup() { 38 mIsAvailable = false 39 } 40 41 @RequiresPermission(BLUETOOTH_ADVERTISE) 42 private fun getManager(source: AttributionSource): AdvertiseManager? { 43 if (!Utils.checkAdvertisePermissionForDataDelivery(mContext, source, "AdvertiseManager")) { 44 return null 45 } 46 return if (mIsAvailable) mAdvertiseManager else null 47 } 48 49 override fun startAdvertisingSet( 50 parameters: AdvertisingSetParameters, 51 advertiseData: AdvertiseData?, 52 scanResponse: AdvertiseData?, 53 periodicParameters: PeriodicAdvertisingParameters?, 54 periodicData: AdvertiseData?, 55 duration: Int, 56 maxExtAdvEvents: Int, 57 serverIf: Int, 58 callback: IAdvertisingSetCallback, 59 source: AttributionSource, 60 ) { 61 if ( 62 parameters.ownAddressType != AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT || 63 serverIf != 0 || 64 parameters.isDirected 65 ) { 66 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null) 67 } 68 69 getManager(source)?.let { manager -> 70 manager.doOnAdvertiseThread { 71 manager.startAdvertisingSet( 72 parameters, 73 advertiseData, 74 scanResponse, 75 periodicParameters, 76 periodicData, 77 duration, 78 maxExtAdvEvents, 79 serverIf, 80 callback, 81 source, 82 ) 83 } 84 } 85 } 86 87 override fun stopAdvertisingSet(callback: IAdvertisingSetCallback, source: AttributionSource) { 88 getManager(source)?.let { manager -> 89 manager.doOnAdvertiseThread { manager.stopAdvertisingSet(callback) } 90 } 91 } 92 93 override fun getOwnAddress(advertiserId: Int, source: AttributionSource) { 94 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null) 95 getManager(source)?.let { manager -> 96 manager.doOnAdvertiseThread { manager.getOwnAddress(advertiserId) } 97 } 98 } 99 100 override fun enableAdvertisingSet( 101 advertiserId: Int, 102 enable: Boolean, 103 duration: Int, 104 maxExtAdvEvents: Int, 105 source: AttributionSource, 106 ) { 107 getManager(source)?.let { manager -> 108 manager.doOnAdvertiseThread { 109 manager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents) 110 } 111 } 112 } 113 114 override fun setAdvertisingData( 115 advertiserId: Int, 116 data: AdvertiseData?, 117 source: AttributionSource, 118 ) { 119 getManager(source)?.let { manager -> 120 manager.doOnAdvertiseThread { manager.setAdvertisingData(advertiserId, data) } 121 } 122 } 123 124 override fun setScanResponseData( 125 advertiserId: Int, 126 data: AdvertiseData?, 127 source: AttributionSource, 128 ) { 129 getManager(source)?.let { manager -> 130 manager.doOnAdvertiseThread { manager.setScanResponseData(advertiserId, data) } 131 } 132 } 133 134 override fun setAdvertisingParameters( 135 advertiserId: Int, 136 parameters: AdvertisingSetParameters, 137 source: AttributionSource, 138 ) { 139 if ( 140 parameters.ownAddressType != AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT || 141 parameters.isDirected 142 ) { 143 mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null) 144 } 145 getManager(source)?.let { manager -> 146 manager.doOnAdvertiseThread { 147 manager.setAdvertisingParameters(advertiserId, parameters) 148 } 149 } 150 } 151 152 override fun setPeriodicAdvertisingParameters( 153 advertiserId: Int, 154 parameters: PeriodicAdvertisingParameters?, 155 source: AttributionSource, 156 ) { 157 getManager(source)?.let { manager -> 158 manager.doOnAdvertiseThread { 159 manager.setPeriodicAdvertisingParameters(advertiserId, parameters) 160 } 161 } 162 } 163 164 override fun setPeriodicAdvertisingData( 165 advertiserId: Int, 166 data: AdvertiseData?, 167 source: AttributionSource, 168 ) { 169 getManager(source)?.let { manager -> 170 manager.doOnAdvertiseThread { manager.setPeriodicAdvertisingData(advertiserId, data) } 171 } 172 } 173 174 override fun setPeriodicAdvertisingEnable( 175 advertiserId: Int, 176 enable: Boolean, 177 source: AttributionSource, 178 ) { 179 getManager(source)?.let { manager -> 180 manager.doOnAdvertiseThread { 181 manager.setPeriodicAdvertisingEnable(advertiserId, enable) 182 } 183 } 184 } 185 } 186