• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.google.uwb.support.fira;
18 
19 import static com.android.internal.util.Preconditions.checkArgument;
20 
21 import static java.util.Objects.requireNonNull;
22 
23 import android.os.PersistableBundle;
24 import android.uwb.RangingSession;
25 import android.uwb.UwbAddress;
26 
27 import androidx.annotation.Nullable;
28 
29 /**
30  * UWB parameters used to reconfigure a FiRa session. Supports peer adding/removing.
31  *
32  * <p>This is passed as a bundle to the service API {@link RangingSession#reconfigure}.
33  */
34 public class FiraRangingReconfigureParams extends FiraParams {
35     private static final int BUNDLE_VERSION_1 = 1;
36     private static final int BUNDLE_VERSION_CURRENT = BUNDLE_VERSION_1;
37 
38     @Nullable @MulticastListUpdateAction private final Integer mAction;
39     @Nullable private final UwbAddress[] mAddressList;
40     @Nullable private final int[] mSubSessionIdList;
41 
42     @Nullable private final Integer mBlockStrideLength;
43 
44     @Nullable @RangeDataNtfConfig private final Integer mRangeDataNtfConfig;
45     @Nullable private final Integer mRangeDataProximityNear;
46     @Nullable private final Integer mRangeDataProximityFar;
47 
48     private static final String KEY_ACTION = "action";
49     private static final String KEY_MAC_ADDRESS_MODE = "mac_address_mode";
50     private static final String KEY_ADDRESS_LIST = "address_list";
51     private static final String KEY_SUB_SESSION_ID_LIST = "sub_session_id_list";
52     private static final String KEY_UPDATE_BLOCK_STRIDE_LENGTH = "update_block_stride_length";
53     private static final String KEY_UPDATE_RANGE_DATA_NTF_CONFIG = "update_range_data_ntf_config";
54     private static final String KEY_UPDATE_RANGE_DATA_NTF_PROXIMITY_NEAR =
55             "update_range_data_proximity_near";
56     private static final String KEY_UPDATE_RANGE_DATA_NTF_PROXIMITY_FAR =
57             "update_range_data_proximity_far";
58 
FiraRangingReconfigureParams( @ullable @ulticastListUpdateAction Integer action, @Nullable UwbAddress[] addressList, @Nullable int[] subSessionIdList, @Nullable Integer blockStrideLength, @Nullable Integer rangeDataNtfConfig, @Nullable Integer rangeDataProximityNear, @Nullable Integer rangeDataProximityFar)59     private FiraRangingReconfigureParams(
60             @Nullable @MulticastListUpdateAction Integer action,
61             @Nullable UwbAddress[] addressList,
62             @Nullable int[] subSessionIdList,
63             @Nullable Integer blockStrideLength,
64             @Nullable Integer rangeDataNtfConfig,
65             @Nullable Integer rangeDataProximityNear,
66             @Nullable Integer rangeDataProximityFar) {
67         mAction = action;
68         mAddressList = addressList;
69         mSubSessionIdList = subSessionIdList;
70         mBlockStrideLength = blockStrideLength;
71         mRangeDataNtfConfig = rangeDataNtfConfig;
72         mRangeDataProximityNear = rangeDataProximityNear;
73         mRangeDataProximityFar = rangeDataProximityFar;
74     }
75 
76     @Override
getBundleVersion()77     protected int getBundleVersion() {
78         return BUNDLE_VERSION_CURRENT;
79     }
80 
81     @Nullable
82     @MulticastListUpdateAction
getAction()83     public Integer getAction() {
84         return mAction;
85     }
86 
87     @Nullable
getAddressList()88     public UwbAddress[] getAddressList() {
89         return mAddressList;
90     }
91 
92     @Nullable
getSubSessionIdList()93     public int[] getSubSessionIdList() {
94         return mSubSessionIdList;
95     }
96 
97     @Nullable
getBlockStrideLength()98     public Integer getBlockStrideLength() {
99         return mBlockStrideLength;
100     }
101 
102     @Nullable
getRangeDataNtfConfig()103     public Integer getRangeDataNtfConfig() {
104         return mRangeDataNtfConfig;
105     }
106 
107     @Nullable
getRangeDataProximityNear()108     public Integer getRangeDataProximityNear() {
109         return mRangeDataProximityNear;
110     }
111 
112     @Nullable
getRangeDataProximityFar()113     public Integer getRangeDataProximityFar() {
114         return mRangeDataProximityFar;
115     }
116 
117     @Override
toBundle()118     public PersistableBundle toBundle() {
119         PersistableBundle bundle = super.toBundle();
120         if (mAction != null) {
121             requireNonNull(mAddressList);
122             bundle.putInt(KEY_ACTION, mAction);
123 
124             long[] addressList = new long[mAddressList.length];
125             int i = 0;
126             for (UwbAddress address : mAddressList) {
127                 addressList[i++] = uwbAddressToLong(address);
128             }
129             int macAddressMode = MAC_ADDRESS_MODE_2_BYTES;
130             if (mAddressList[0].size() == UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH) {
131                 macAddressMode = MAC_ADDRESS_MODE_8_BYTES;
132             }
133             bundle.putInt(KEY_MAC_ADDRESS_MODE, macAddressMode);
134             bundle.putLongArray(KEY_ADDRESS_LIST, addressList);
135             bundle.putIntArray(KEY_SUB_SESSION_ID_LIST, mSubSessionIdList);
136         }
137 
138         if (mBlockStrideLength != null) {
139             bundle.putInt(KEY_UPDATE_BLOCK_STRIDE_LENGTH, mBlockStrideLength);
140         }
141 
142         if (mRangeDataNtfConfig != null) {
143             bundle.putInt(KEY_UPDATE_RANGE_DATA_NTF_CONFIG, mRangeDataNtfConfig);
144         }
145 
146         if (mRangeDataProximityNear != null) {
147             bundle.putInt(KEY_UPDATE_RANGE_DATA_NTF_PROXIMITY_NEAR, mRangeDataProximityNear);
148         }
149 
150         if (mRangeDataProximityFar != null) {
151             bundle.putInt(KEY_UPDATE_RANGE_DATA_NTF_PROXIMITY_FAR, mRangeDataProximityFar);
152         }
153 
154         return bundle;
155     }
156 
fromBundle(PersistableBundle bundle)157     public static FiraRangingReconfigureParams fromBundle(PersistableBundle bundle) {
158         if (!isCorrectProtocol(bundle)) {
159             throw new IllegalArgumentException("Invalid protocol");
160         }
161 
162         switch (getBundleVersion(bundle)) {
163             case BUNDLE_VERSION_1:
164                 return parseVersion1(bundle);
165 
166             default:
167                 throw new IllegalArgumentException("Invalid bundle version");
168         }
169     }
170 
parseVersion1(PersistableBundle bundle)171     private static FiraRangingReconfigureParams parseVersion1(PersistableBundle bundle) {
172         FiraRangingReconfigureParams.Builder builder = new FiraRangingReconfigureParams.Builder();
173         if (bundle.containsKey(KEY_ACTION)) {
174             int macAddressMode = bundle.getInt(KEY_MAC_ADDRESS_MODE);
175             int addressByteLength = UwbAddress.SHORT_ADDRESS_BYTE_LENGTH;
176             if (macAddressMode == MAC_ADDRESS_MODE_8_BYTES) {
177                 addressByteLength = UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH;
178             }
179 
180             long[] addresses = bundle.getLongArray(KEY_ADDRESS_LIST);
181             UwbAddress[] addressList = new UwbAddress[addresses.length];
182             for (int i = 0; i < addresses.length; i++) {
183                 addressList[i] = longToUwbAddress(addresses[i], addressByteLength);
184             }
185             builder.setAction(bundle.getInt(KEY_ACTION))
186                     .setAddressList(addressList)
187                     .setSubSessionIdList(bundle.getIntArray(KEY_SUB_SESSION_ID_LIST));
188         }
189 
190         if (bundle.containsKey(KEY_UPDATE_BLOCK_STRIDE_LENGTH)) {
191             builder.setBlockStrideLength(bundle.getInt(KEY_UPDATE_BLOCK_STRIDE_LENGTH));
192         }
193 
194         if (bundle.containsKey(KEY_UPDATE_RANGE_DATA_NTF_CONFIG)) {
195             builder.setRangeDataNtfConfig(bundle.getInt(KEY_UPDATE_RANGE_DATA_NTF_CONFIG));
196         }
197 
198         if (bundle.containsKey(KEY_UPDATE_RANGE_DATA_NTF_PROXIMITY_NEAR)) {
199             builder.setRangeDataProximityNear(
200                     bundle.getInt(KEY_UPDATE_RANGE_DATA_NTF_PROXIMITY_NEAR));
201         }
202 
203         if (bundle.containsKey(KEY_UPDATE_RANGE_DATA_NTF_PROXIMITY_FAR)) {
204             builder.setRangeDataProximityFar(
205                     bundle.getInt(KEY_UPDATE_RANGE_DATA_NTF_PROXIMITY_FAR));
206         }
207 
208         return builder.build();
209     }
210 
211     /** Builder */
212     public static class Builder {
213         @Nullable private Integer mAction = null;
214         @Nullable private UwbAddress[] mAddressList = null;
215         @Nullable private int[] mSubSessionIdList = null;
216 
217         @Nullable private Integer mBlockStrideLength = null;
218 
219         @Nullable private Integer mRangeDataNtfConfig = null;
220         @Nullable private Integer mRangeDataProximityNear = null;
221         @Nullable private Integer mRangeDataProximityFar = null;
222 
setAction( @ulticastListUpdateAction int action)223         public FiraRangingReconfigureParams.Builder setAction(
224                 @MulticastListUpdateAction int action) {
225             mAction = action;
226             return this;
227         }
228 
setAddressList(UwbAddress[] addressList)229         public FiraRangingReconfigureParams.Builder setAddressList(UwbAddress[] addressList) {
230             mAddressList = addressList;
231             return this;
232         }
233 
setSubSessionIdList(int[] subSessionIdList)234         public FiraRangingReconfigureParams.Builder setSubSessionIdList(int[] subSessionIdList) {
235             mSubSessionIdList = subSessionIdList;
236             return this;
237         }
238 
setBlockStrideLength(int blockStrideLength)239         public FiraRangingReconfigureParams.Builder setBlockStrideLength(int blockStrideLength) {
240             mBlockStrideLength = blockStrideLength;
241             return this;
242         }
243 
setRangeDataNtfConfig(int rangeDataNtfConfig)244         public FiraRangingReconfigureParams.Builder setRangeDataNtfConfig(int rangeDataNtfConfig) {
245             mRangeDataNtfConfig = rangeDataNtfConfig;
246             return this;
247         }
248 
setRangeDataProximityNear( int rangeDataProximityNear)249         public FiraRangingReconfigureParams.Builder setRangeDataProximityNear(
250                 int rangeDataProximityNear) {
251             mRangeDataProximityNear = rangeDataProximityNear;
252             return this;
253         }
254 
setRangeDataProximityFar( int rangeDataProximityFar)255         public FiraRangingReconfigureParams.Builder setRangeDataProximityFar(
256                 int rangeDataProximityFar) {
257             mRangeDataProximityFar = rangeDataProximityFar;
258             return this;
259         }
260 
checkAddressList()261         private void checkAddressList() {
262             checkArgument(mAddressList != null && mAddressList.length > 0);
263             for (UwbAddress uwbAddress : mAddressList) {
264                 requireNonNull(uwbAddress);
265                 checkArgument(uwbAddress.size() == UwbAddress.SHORT_ADDRESS_BYTE_LENGTH);
266             }
267 
268             checkArgument(
269                     mSubSessionIdList == null || mSubSessionIdList.length == mAddressList.length);
270         }
271 
build()272         public FiraRangingReconfigureParams build() {
273             if (mAction != null) {
274                 checkAddressList();
275                 // Either update the address list or update ranging parameters. Not both.
276                 checkArgument(
277                         mBlockStrideLength == null
278                                 && mRangeDataNtfConfig == null
279                                 && mRangeDataProximityNear == null
280                                 && mRangeDataProximityFar == null);
281             } else {
282                 checkArgument(
283                         mBlockStrideLength != null
284                                 || mRangeDataNtfConfig != null
285                                 || mRangeDataProximityNear != null
286                                 || mRangeDataProximityFar != null);
287             }
288 
289             return new FiraRangingReconfigureParams(
290                     mAction,
291                     mAddressList,
292                     mSubSessionIdList,
293                     mBlockStrideLength,
294                     mRangeDataNtfConfig,
295                     mRangeDataProximityNear,
296                     mRangeDataProximityFar);
297         }
298     }
299 }
300