• 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 
17 package com.android.bluetooth.le_scan;
18 
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.List;
22 
23 /**
24  * Helper class to keep track of MSFT patterns, their filter index, and number of monitors
25  * registered with that pattern. Some chipsets don't support multiple monitors with the same
26  * pattern. To solve that and to generally ease their task, we merge monitors with the same pattern,
27  * so those monitors will only be sent once.
28  */
29 class MsftAdvMonitorMergedPatternList {
30     static class MsftAdvMonitorMergedPattern {
31         private final MsftAdvMonitor.Pattern[] mPatterns;
32         private final int mFilterIndex;
33         private int mCount = 0;
34 
MsftAdvMonitorMergedPattern(MsftAdvMonitor.Pattern[] pattern, int filterIndex)35         MsftAdvMonitorMergedPattern(MsftAdvMonitor.Pattern[] pattern, int filterIndex) {
36             mPatterns = pattern;
37             mFilterIndex = filterIndex;
38         }
39     }
40 
41     List<MsftAdvMonitorMergedPattern> mMergedPatterns = new ArrayList<>();
42 
43     // Two patterns are considered equal if they have the exact same pattern
44     // in the same order. Therefore A+B and B+A are considered different, as
45     // well as A and A+A. This shouldn't causes issues but could be optimized.
46     // Returns merged pattern or null if not found.
getMergedPattern(MsftAdvMonitor.Pattern[] pattern)47     private MsftAdvMonitorMergedPattern getMergedPattern(MsftAdvMonitor.Pattern[] pattern) {
48         return mMergedPatterns.stream()
49                 .filter(mergedPattern -> Arrays.equals(mergedPattern.mPatterns, pattern))
50                 .findFirst()
51                 .orElse(null);
52     }
53 
54     // If pattern doesn't exist, creates new entry with given index.
55     // If pattern exists, increases count and returns filter index.
add(int filterIndex, MsftAdvMonitor.Pattern[] pattern)56     int add(int filterIndex, MsftAdvMonitor.Pattern[] pattern) {
57         MsftAdvMonitorMergedPattern mergedPattern = (getMergedPattern(pattern));
58         if (mergedPattern == null) {
59             mergedPattern = new MsftAdvMonitorMergedPattern(pattern, filterIndex);
60             mMergedPatterns.add(mergedPattern);
61         }
62 
63         mergedPattern.mCount++;
64         return mergedPattern.mFilterIndex;
65     }
66 
67     // If pattern exists, decreases count. If count is 0, removes entry.
68     // Returns true if there are no more instances of the given filter index
remove(int filterIndex)69     boolean remove(int filterIndex) {
70         mMergedPatterns.stream()
71                 .filter(pattern -> pattern.mFilterIndex == filterIndex)
72                 .forEach(pattern -> pattern.mCount--);
73         return mMergedPatterns.removeIf(pattern -> pattern.mCount == 0);
74     }
75 }
76