• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.google.uwb.support.fira;
17 
18 import android.os.PersistableBundle;
19 import android.uwb.UwbAddress;
20 
21 import androidx.annotation.Nullable;
22 
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 import java.util.ArrayList;
26 import java.util.List;
27 
28 /**
29  * Uwb data transfer phase configuration
30  */
31 public class FiraDataTransferPhaseConfig extends FiraParams {
32     private static final int BUNDLE_VERSION_1 = 1;
33     private static final int BUNDLE_VERSION_CURRENT = BUNDLE_VERSION_1;
34     private static final int SHORT_MAC_ADDRESS = 0;
35 
36     private final byte mDtpcmRepetition;
37     private final byte mDataTransferControl;
38     private final List<FiraDataTransferPhaseManagementList> mDataTransferPhaseManagementList;
39 
40     private static final String KEY_BUNDLE_VERSION = "bundle_version";
41     private static final String KEY_DTPCM_REPETITION = "dtpcm_repetition";
42     private static final String KEY_DATA_TRANSFER_CONTROL = "data_transfer_control";
43     private static final String KEY_MAC_ADDRESS_LIST = "mac_address";
44     private static final String KEY_SLOT_BITMAP = "slot_bitmap";
45     private static final String KEY_STOP_DATA_TRANSFER = "stop_data_transfer";
46 
47     @Override
getBundleVersion()48     public int getBundleVersion() {
49         return BUNDLE_VERSION_CURRENT;
50     }
51 
getDtpcmRepetition()52     public byte getDtpcmRepetition() {
53         return mDtpcmRepetition;
54     }
55 
getDataTransferControl()56     public byte getDataTransferControl() {
57         return mDataTransferControl;
58     }
59 
getDataTransferPhaseManagementList()60     public List<FiraDataTransferPhaseManagementList> getDataTransferPhaseManagementList() {
61         return mDataTransferPhaseManagementList;
62     }
63 
FiraDataTransferPhaseConfig(byte dtpcmRepetition, byte dataTransferControl, List<FiraDataTransferPhaseManagementList> dataTransferPhaseManagementList)64     private FiraDataTransferPhaseConfig(byte dtpcmRepetition, byte dataTransferControl,
65             List<FiraDataTransferPhaseManagementList> dataTransferPhaseManagementList) {
66         mDtpcmRepetition = dtpcmRepetition;
67         mDataTransferControl = dataTransferControl;
68         mDataTransferPhaseManagementList = dataTransferPhaseManagementList;
69     }
70 
71     @Override
toBundle()72     public PersistableBundle toBundle() {
73         PersistableBundle bundle = super.toBundle();
74         bundle.putInt(KEY_BUNDLE_VERSION, getBundleVersion());
75         bundle.putInt(KEY_DTPCM_REPETITION, mDtpcmRepetition);
76         bundle.putInt(KEY_DATA_TRANSFER_CONTROL, mDataTransferControl);
77 
78         int dataTransferPhaseManagementListSize = mDataTransferPhaseManagementList.size();
79         long[] macAddressList = new long[dataTransferPhaseManagementListSize];
80         int i = 0;
81         ByteBuffer slotBitmapByteBuffer = ByteBuffer.allocate(dataTransferPhaseManagementListSize
82                 * (1 << ((mDataTransferControl & 0x0F) >> 1)));
83 
84         slotBitmapByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
85         ByteBuffer stopDataTransferBuffer =
86                 ByteBuffer.allocate(dataTransferPhaseManagementListSize);
87 
88         for (FiraDataTransferPhaseManagementList dataTransferPhaseManagementList :
89                 mDataTransferPhaseManagementList) {
90             macAddressList[i++] = uwbAddressToLong(
91                 dataTransferPhaseManagementList.getUwbAddress());
92             slotBitmapByteBuffer.put(dataTransferPhaseManagementList.getSlotBitMap());
93             stopDataTransferBuffer.put(dataTransferPhaseManagementList.getStopDataTransfer());
94         }
95 
96         bundle.putLongArray(KEY_MAC_ADDRESS_LIST, macAddressList);
97         bundle.putIntArray(KEY_SLOT_BITMAP, byteArrayToIntArray(slotBitmapByteBuffer.array()));
98         bundle.putIntArray(KEY_STOP_DATA_TRANSFER, byteArrayToIntArray(
99                 stopDataTransferBuffer.array()));
100 
101         return bundle;
102     }
103 
104     @Nullable
byteArrayToIntArray(@ullable byte[] bytes)105     protected static int[] byteArrayToIntArray(@Nullable byte[] bytes) {
106         if (bytes == null) {
107             return null;
108         }
109 
110         int[] values = new int[bytes.length];
111         for (int i = 0; i < values.length; i++) {
112             values[i] = bytes[i];
113         }
114         return values;
115     }
116 
117     @Nullable
intArrayToByteArray(@ullable int[] values)118     protected static byte[] intArrayToByteArray(@Nullable int[] values) {
119         if (values == null) {
120             return null;
121         }
122         byte[] bytes = new byte[values.length];
123         for (int i = 0; i < values.length; i++) {
124             bytes[i] = (byte) values[i];
125         }
126         return bytes;
127     }
128 
fromBundle(PersistableBundle bundle)129     public static FiraDataTransferPhaseConfig fromBundle(PersistableBundle bundle) {
130         switch (bundle.getInt(KEY_BUNDLE_VERSION)) {
131             case BUNDLE_VERSION_1:
132                 return parseVersion1(bundle);
133             default:
134                 throw new IllegalArgumentException("Invalid bundle version");
135         }
136     }
137 
parseVersion1(PersistableBundle bundle)138     private static FiraDataTransferPhaseConfig parseVersion1(PersistableBundle bundle) {
139         FiraDataTransferPhaseConfig.Builder builder = new FiraDataTransferPhaseConfig.Builder();
140 
141         builder.setDtpcmRepetition((byte) bundle.getInt(KEY_DTPCM_REPETITION));
142         byte dataTransferControl = (byte) bundle.getInt(KEY_DATA_TRANSFER_CONTROL);
143         builder.setMacAddressMode((byte) (dataTransferControl & 0x01));
144         builder.setSlotBitmapSize((byte) ((dataTransferControl & 0x0F) >> 1));
145 
146         List<FiraDataTransferPhaseManagementList> mDataTransferPhaseManagementList =
147                 new ArrayList<>();
148         List<UwbAddress> macAddressList = new ArrayList<>();
149         List<byte[]> slotBitmapList = new ArrayList<>();
150         List<Byte> stopDataTransferList = new ArrayList<>();
151         long[] macAddress = bundle.getLongArray(KEY_MAC_ADDRESS_LIST);
152         for (int i = 0; i < macAddress.length; i++) {
153             macAddressList.add(longToUwbAddress(macAddress[i],
154                     ((dataTransferControl & 0x01) == SHORT_MAC_ADDRESS)
155                     ? UwbAddress.SHORT_ADDRESS_BYTE_LENGTH
156                         : UwbAddress.EXTENDED_ADDRESS_BYTE_LENGTH));
157         }
158 
159         byte[] buffer = intArrayToByteArray(bundle.getIntArray(KEY_SLOT_BITMAP));
160         ByteBuffer slotBitmapByteBuffer = ByteBuffer.wrap(buffer);
161         int chunkBufferSize = 1 << (dataTransferControl >> 1);
162 
163         while (slotBitmapByteBuffer.hasRemaining()) {
164             byte[] data = new byte[chunkBufferSize];
165             int bytesToRead = Math.min(chunkBufferSize, slotBitmapByteBuffer.remaining());
166             slotBitmapByteBuffer.get(data, 0, bytesToRead);
167             slotBitmapList.add(data);
168         }
169 
170         byte[] stopBuffer = intArrayToByteArray(bundle.getIntArray(KEY_STOP_DATA_TRANSFER));
171         for (int i = 0; i < stopBuffer.length; i++) {
172             stopDataTransferList.add(stopBuffer[i]);
173         }
174 
175 
176         for (int i = 0; i < macAddressList.size(); i++) {
177             mDataTransferPhaseManagementList.add(new FiraDataTransferPhaseManagementList(
178                     macAddressList.get(i), slotBitmapList.get(i), stopDataTransferList.get(i)));
179         }
180 
181         builder.setDataTransferPhaseManagementList(mDataTransferPhaseManagementList);
182 
183         return builder.build();
184     }
185 
186     /** Defines parameters for data transfer phase management list */
187     public static class FiraDataTransferPhaseManagementList {
188         private final UwbAddress mUwbAddress;
189         private final byte[] mSlotBitMap;
190         private final byte mStopDataTransfer;
191 
FiraDataTransferPhaseManagementList(UwbAddress uwbAddress, byte[] slotBitmap, byte stopDataTransfer)192         public FiraDataTransferPhaseManagementList(UwbAddress uwbAddress, byte[] slotBitmap,
193                 byte stopDataTransfer) {
194             mUwbAddress = uwbAddress;
195             mSlotBitMap = slotBitmap;
196             mStopDataTransfer = stopDataTransfer;
197         }
198 
getUwbAddress()199         public UwbAddress getUwbAddress() {
200             return mUwbAddress;
201         }
202 
getSlotBitMap()203         public byte[] getSlotBitMap() {
204             return mSlotBitMap;
205         }
getStopDataTransfer()206         public byte getStopDataTransfer() {
207             return mStopDataTransfer;
208         }
209     }
210 
211     /** Builder */
212     public static class Builder {
213         private byte mDtpcmRepetition;
214         private byte mMacAddressMode;
215         private byte mSlotBitMapSize;
216         private List<FiraDataTransferPhaseManagementList> mDataTransferPhaseManagementList =
217                 new ArrayList<>();
218 
setDtpcmRepetition(byte dtpcmRepetition)219         public FiraDataTransferPhaseConfig.Builder setDtpcmRepetition(byte dtpcmRepetition) {
220             mDtpcmRepetition = dtpcmRepetition;
221             return this;
222         }
223 
setMacAddressMode(byte macAddressMode)224         public FiraDataTransferPhaseConfig.Builder setMacAddressMode(byte macAddressMode) {
225             mMacAddressMode = macAddressMode;
226             return this;
227         }
228 
setSlotBitmapSize(byte slotBitmapSize)229         public FiraDataTransferPhaseConfig.Builder setSlotBitmapSize(byte slotBitmapSize) {
230             mSlotBitMapSize = slotBitmapSize;
231             return this;
232         }
233 
setDataTransferPhaseManagementList( List<FiraDataTransferPhaseManagementList> dataTransferPhaseManagementList)234         public FiraDataTransferPhaseConfig.Builder setDataTransferPhaseManagementList(
235                 List<FiraDataTransferPhaseManagementList> dataTransferPhaseManagementList) {
236             mDataTransferPhaseManagementList = dataTransferPhaseManagementList;
237             return this;
238         }
239 
build()240         public FiraDataTransferPhaseConfig build() {
241             return new FiraDataTransferPhaseConfig(
242                 mDtpcmRepetition,
243                 (byte) ((mSlotBitMapSize << 1) | (mMacAddressMode & 0x01)),
244                 mDataTransferPhaseManagementList);
245         }
246     }
247 }
248