1 /* 2 * Copyright 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 com.google.common.collect.ImmutableList; 22 23 import java.nio.ByteBuffer; 24 import java.nio.ByteOrder; 25 import java.util.BitSet; 26 import java.util.List; 27 28 /** 29 * Utilities for {@link com.android.ranging}. 30 */ 31 public class RangingUtils { 32 /** 33 * A basic synchronized state machine. 34 * @param <E> enum representing the different states of the machine. 35 */ 36 public static class StateMachine<E extends Enum<E>> { 37 private E mState; 38 StateMachine(E start)39 public StateMachine(E start) { 40 mState = start; 41 } 42 43 /** Gets the current state */ getState()44 public synchronized E getState() { 45 return mState; 46 } 47 48 /** Sets the current state */ setState(E state)49 public synchronized void setState(E state) { 50 mState = state; 51 } 52 53 /** 54 * Sets the current state. 55 * @return true if the state was successfully changed, false if the current state is 56 * already {@code state}. 57 */ changeStateTo(E state)58 public synchronized boolean changeStateTo(E state) { 59 if (mState == state) { 60 return false; 61 } 62 setState(state); 63 return true; 64 } 65 66 /** 67 * If the current state is {@code from}, sets it to {@code to}. 68 * @return true if the current state is {@code from}, false otherwise. 69 */ transition(E from, E to)70 public synchronized boolean transition(E from, E to) { 71 if (mState != from) { 72 return false; 73 } 74 mState = to; 75 return true; 76 } 77 78 @Override toString()79 public String toString() { 80 return "StateMachine{ " 81 + mState 82 + "}"; 83 } 84 } 85 86 public static class Conversions { 87 /** 88 * Converts a list of integers to a byte array representing a bitmap of the integers. Given 89 * integers are first shifted by the shift param amount before being placed into the bitmap 90 * (e.g int x results in bit at pos "x - shift" being set). 91 */ intListToByteArrayBitmap( List<Integer> list, int expectedSizeBytes, int shift)92 public static byte[] intListToByteArrayBitmap( 93 List<Integer> list, int expectedSizeBytes, int shift) { 94 BitSet bitSet = new BitSet(expectedSizeBytes * 8); 95 for (int i : list) { 96 bitSet.set(i - shift); 97 } 98 byte[] byteArray = new byte[expectedSizeBytes]; 99 System.arraycopy(bitSet.toByteArray(), 0, byteArray, 0, 100 min(expectedSizeBytes, bitSet.toByteArray().length)); 101 return byteArray; 102 } 103 104 /** 105 * Converts a byte array representing a bitmap of integers to a list of integers. The 106 * resulting integers are shifted by the shift param amount (e.g bit set at pos x results 107 * to "x + shift" int in the final list). 108 */ byteArrayToIntList(byte[] byteArray, int shift)109 public static ImmutableList<Integer> byteArrayToIntList(byte[] byteArray, int shift) { 110 ImmutableList.Builder<Integer> list = ImmutableList.builder(); 111 BitSet bitSet = BitSet.valueOf(byteArray); 112 for (int i = 0; i < bitSet.length(); i++) { 113 if (bitSet.get(i)) { 114 list.add(i + shift); 115 } 116 } 117 return list.build(); 118 } 119 120 /** Converts an int to a byte array of a given size, using little endianness. */ intToByteArray(int value, int expectedSizeBytes)121 public static byte[] intToByteArray(int value, int expectedSizeBytes) { 122 ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); 123 buffer.putInt(value).rewind(); 124 byte[] byteArray = new byte[expectedSizeBytes]; 125 buffer.get(byteArray, 0, min(expectedSizeBytes, 4)); 126 return byteArray; 127 } 128 129 /** Converts the given byte array to an integer using little endianness. */ byteArrayToInt(byte[] byteArray)130 public static int byteArrayToInt(byte[] byteArray) { 131 ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); 132 buffer.put(byteArray).rewind(); 133 return buffer.getInt(); 134 } 135 } 136 } 137