• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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