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.server.ranging;
18 
19 import static java.lang.Math.min;
20 
21 import android.content.Context;
22 import android.ranging.RangingManager;
23 
24 import com.android.server.ranging.blerssi.BleRssiCapabilitiesAdapter;
25 import com.android.server.ranging.cs.CsCapabilitiesAdapter;
26 import com.android.server.ranging.rtt.RttCapabilitiesAdapter;
27 import com.android.server.ranging.uwb.UwbCapabilitiesAdapter;
28 
29 import com.google.common.collect.ImmutableList;
30 
31 import java.util.BitSet;
32 import java.util.List;
33 
34 /** Enum representing an individual ranging technology. */
35 public enum RangingTechnology {
36     UWB(0), // Ultra-Wide Band
37     CS(1), // Channel Sounding, formerly known as HADM
38 
39     RTT(2), // Wifi RTT.
40     RSSI(3); // BLE RSSI.
41 
42     public static final ImmutableList<RangingTechnology> TECHNOLOGIES =
43             ImmutableList.copyOf(RangingTechnology.values());
44 
45     private static final int BITMAP_SIZE_BYTES = 2;
46 
47     private final int value;
48 
RangingTechnology(int value)49     RangingTechnology(int value) {
50         this.value = value;
51     }
52 
getValue()53     public @RangingManager.RangingTechnology int getValue() {
54         return value;
55     }
56 
toByte()57     public byte toByte() {
58         return (byte) value;
59     }
60 
61     /**
62      * Check whether this technology is available given the provided context.
63      * @return true if the technology is supported, false otherwise.
64      */
isSupported(Context context)65     public boolean isSupported(Context context) {
66         switch (this) {
67             case UWB:
68                 return UwbCapabilitiesAdapter.isSupported(context);
69             case CS:
70                 return CsCapabilitiesAdapter.isSupported(context);
71             case RTT:
72                 return RttCapabilitiesAdapter.isSupported(context);
73             case RSSI:
74                 return BleRssiCapabilitiesAdapter.isSupported(context);
75             default:
76                 return false;
77         }
78     }
79 
parseByte(byte technologiesByte)80     public static ImmutableList<RangingTechnology> parseByte(byte technologiesByte) {
81         BitSet bitset = BitSet.valueOf(new byte[]{technologiesByte});
82         ImmutableList.Builder<RangingTechnology> technologies = ImmutableList.builder();
83         for (RangingTechnology technology : RangingTechnology.values()) {
84             if (bitset.get(technology.value)) {
85                 technologies.add(technology);
86             }
87         }
88         return technologies.build();
89     }
90 
toBitmap(List<RangingTechnology> technologies)91     public static byte[] toBitmap(List<RangingTechnology> technologies) {
92         if (technologies.isEmpty()) {
93             return new byte[BITMAP_SIZE_BYTES];
94         }
95         BitSet bitset = new BitSet(BITMAP_SIZE_BYTES * 8);
96         for (RangingTechnology technology : technologies) {
97             bitset.set(technology.value);
98         }
99         byte[] bitmap = new byte[BITMAP_SIZE_BYTES];
100         System.arraycopy(
101                 bitset.toByteArray(), 0, bitmap, 0,
102                 min(BITMAP_SIZE_BYTES, bitset.toByteArray().length));
103         return bitmap;
104     }
105 
fromBitmap(byte[] technologiesBitmap)106     public static ImmutableList<RangingTechnology> fromBitmap(byte[] technologiesBitmap) {
107         ImmutableList.Builder<RangingTechnology> techs = ImmutableList.builder();
108         BitSet bitSet = BitSet.valueOf(technologiesBitmap);
109         for (int i = 0; i < BITMAP_SIZE_BYTES * 8; i++) {
110             if (bitSet.get(i)) {
111                 if (i < RangingTechnology.values().length) {
112                     techs.add(RangingTechnology.values()[i]);
113                 }
114             }
115         }
116         return techs.build();
117     }
118 }