• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 com.android.bluetooth.gatt;
17 
18 import android.bluetooth.le.AdvertiseData;
19 import android.bluetooth.le.AdvertisingSetParameters;
20 import android.bluetooth.le.PeriodicAdvertisingParameters;
21 import android.content.AttributionSource;
22 import android.content.Context;
23 import android.os.Binder;
24 import android.util.Log;
25 
26 import androidx.annotation.VisibleForTesting;
27 
28 import com.android.bluetooth.BluetoothEventLogger;
29 import com.android.internal.annotations.GuardedBy;
30 
31 import java.util.HashMap;
32 
33 /** Helper class that keeps track of advertiser stats. */
34 class AdvertiserMap {
35     private static final String TAG =
36             GattServiceConfig.TAG_PREFIX + AdvertiserMap.class.getSimpleName();
37 
38     /** Internal map to keep track of logging information by advertise id */
39     @GuardedBy("this")
40     private final HashMap<Integer, AppAdvertiseStats> mAppAdvertiseStats = new HashMap<>();
41 
42     private final BluetoothEventLogger mLastAdvertises =
43             new BluetoothEventLogger(5, "Last Advertising");
44 
45     /** Add an entry to the stats map if it doesn't already exist. */
addAppAdvertiseStats(int id, Context context, AttributionSource attrSource)46     void addAppAdvertiseStats(int id, Context context, AttributionSource attrSource) {
47         int appUid = Binder.getCallingUid();
48         String appName = context.getPackageManager().getNameForUid(appUid);
49         if (appName == null) {
50             // Assign an app name if one isn't found
51             appName = "Unknown App (UID: " + appUid + ")";
52         }
53 
54         synchronized (this) {
55             if (!mAppAdvertiseStats.containsKey(id)) {
56                 addAppAdvertiseStats(id, new AppAdvertiseStats(appUid, id, appName, attrSource));
57             }
58         }
59     }
60 
61     @VisibleForTesting
addAppAdvertiseStats(int id, AppAdvertiseStats stats)62     synchronized void addAppAdvertiseStats(int id, AppAdvertiseStats stats) {
63         mAppAdvertiseStats.put(id, stats);
64     }
65 
66     /** Remove the context for a given application ID. */
removeAppAdvertiseStats(int id)67     synchronized void removeAppAdvertiseStats(int id) {
68         mAppAdvertiseStats.remove(id);
69     }
70 
71     /** Get Logging info by ID */
getAppAdvertiseStatsById(int id)72     synchronized AppAdvertiseStats getAppAdvertiseStatsById(int id) {
73         return mAppAdvertiseStats.get(id);
74     }
75 
76     /** update the advertiser ID by the register ID */
setAdvertiserIdByRegId(int regId, int advertiserId)77     synchronized void setAdvertiserIdByRegId(int regId, int advertiserId) {
78         AppAdvertiseStats stats = mAppAdvertiseStats.get(regId);
79         if (stats == null) {
80             return;
81         }
82         stats.setId(advertiserId);
83         mAppAdvertiseStats.remove(regId);
84         mAppAdvertiseStats.put(advertiserId, stats);
85     }
86 
recordAdvertiseStart( int id, AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents)87     synchronized void recordAdvertiseStart(
88             int id,
89             AdvertisingSetParameters parameters,
90             AdvertiseData advertiseData,
91             AdvertiseData scanResponse,
92             PeriodicAdvertisingParameters periodicParameters,
93             AdvertiseData periodicData,
94             int duration,
95             int maxExtAdvEvents) {
96         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
97         if (stats == null) {
98             return;
99         }
100         int advertiseInstanceCount = mAppAdvertiseStats.size();
101         Log.d(TAG, "advertiseInstanceCount is " + advertiseInstanceCount);
102         AppAdvertiseStats.recordAdvertiseInstanceCount(advertiseInstanceCount);
103         stats.recordAdvertiseStart(
104                 parameters,
105                 advertiseData,
106                 scanResponse,
107                 periodicParameters,
108                 periodicData,
109                 duration,
110                 maxExtAdvEvents,
111                 advertiseInstanceCount);
112     }
113 
recordAdvertiseStop(int id)114     synchronized void recordAdvertiseStop(int id) {
115         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
116         if (stats == null) {
117             return;
118         }
119         stats.recordAdvertiseStop(mAppAdvertiseStats.size());
120         mAppAdvertiseStats.remove(id);
121 
122         StringBuilder sb = new StringBuilder();
123         AppAdvertiseStats.dumpToString(sb, stats);
124         mLastAdvertises.add(sb.toString());
125     }
126 
enableAdvertisingSet( int id, boolean enable, int duration, int maxExtAdvEvents)127     synchronized void enableAdvertisingSet(
128             int id, boolean enable, int duration, int maxExtAdvEvents) {
129         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
130         if (stats == null) {
131             return;
132         }
133         stats.enableAdvertisingSet(enable, duration, maxExtAdvEvents, mAppAdvertiseStats.size());
134     }
135 
setAdvertisingData(int id, AdvertiseData data)136     synchronized void setAdvertisingData(int id, AdvertiseData data) {
137         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
138         if (stats == null) {
139             return;
140         }
141         stats.setAdvertisingData(data);
142     }
143 
setScanResponseData(int id, AdvertiseData data)144     synchronized void setScanResponseData(int id, AdvertiseData data) {
145         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
146         if (stats == null) {
147             return;
148         }
149         stats.setScanResponseData(data);
150     }
151 
setAdvertisingParameters(int id, AdvertisingSetParameters parameters)152     synchronized void setAdvertisingParameters(int id, AdvertisingSetParameters parameters) {
153         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
154         if (stats == null) {
155             return;
156         }
157         stats.setAdvertisingParameters(parameters);
158     }
159 
setPeriodicAdvertisingParameters( int id, PeriodicAdvertisingParameters parameters)160     synchronized void setPeriodicAdvertisingParameters(
161             int id, PeriodicAdvertisingParameters parameters) {
162         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
163         if (stats == null) {
164             return;
165         }
166         stats.setPeriodicAdvertisingParameters(parameters);
167     }
168 
setPeriodicAdvertisingData(int id, AdvertiseData data)169     synchronized void setPeriodicAdvertisingData(int id, AdvertiseData data) {
170         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
171         if (stats == null) {
172             return;
173         }
174         stats.setPeriodicAdvertisingData(data);
175     }
176 
onPeriodicAdvertiseEnabled(int id, boolean enable)177     synchronized void onPeriodicAdvertiseEnabled(int id, boolean enable) {
178         AppAdvertiseStats stats = mAppAdvertiseStats.get(id);
179         if (stats == null) {
180             return;
181         }
182         stats.onPeriodicAdvertiseEnabled(enable);
183     }
184 
185     /** Erases all entries. */
clear()186     synchronized void clear() {
187         mAppAdvertiseStats.clear();
188         mLastAdvertises.clear();
189     }
190 
191     /** Logs advertiser debug information. */
dump(StringBuilder sb)192     synchronized void dump(StringBuilder sb) {
193         mLastAdvertises.dump(sb);
194 
195         if (!mAppAdvertiseStats.isEmpty()) {
196             sb.append("  Total number of ongoing advertising                   : ")
197                     .append(mAppAdvertiseStats.size());
198             sb.append("\n  Ongoing advertising:");
199             for (Integer key : mAppAdvertiseStats.keySet()) {
200                 AppAdvertiseStats stats = mAppAdvertiseStats.get(key);
201                 AppAdvertiseStats.dumpToString(sb, stats);
202             }
203         }
204         sb.append("\n");
205         Log.d(TAG, sb.toString());
206     }
207 }
208