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 android.ranging; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import com.android.ranging.flags.Flags; 26 27 import java.util.Objects; 28 29 /** 30 * Defines the ranging session configurations. 31 * 32 * <p>This class allows apps to set various parameters related to a ranging session. 33 * 34 */ 35 @FlaggedApi(Flags.FLAG_RANGING_STACK_ENABLED) 36 public final class SessionConfig implements Parcelable { 37 private final SensorFusionParams mFusionParams; 38 private final DataNotificationConfig mDataNotificationConfig; 39 private final boolean mIsAngleOfArrivalNeeded; 40 private final int mRangingMeasurementsLimit; 41 SessionConfig(Builder builder)42 private SessionConfig(Builder builder) { 43 mFusionParams = builder.mFusionParams; 44 mDataNotificationConfig = builder.mDataNotificationConfig; 45 mIsAngleOfArrivalNeeded = builder.mIsAngleOfArrivalNeeded; 46 mRangingMeasurementsLimit = builder.mRangingMeasurementsLimit; 47 } 48 SessionConfig(Parcel in)49 private SessionConfig(Parcel in) { 50 mFusionParams = in.readParcelable(SensorFusionParams.class.getClassLoader(), 51 SensorFusionParams.class); 52 mDataNotificationConfig = in.readParcelable(DataNotificationConfig.class.getClassLoader(), 53 DataNotificationConfig.class); 54 mIsAngleOfArrivalNeeded = in.readBoolean(); 55 mRangingMeasurementsLimit = in.readInt(); 56 } 57 58 @Override writeToParcel(@onNull Parcel dest, int flags)59 public void writeToParcel(@NonNull Parcel dest, int flags) { 60 dest.writeParcelable(mFusionParams, flags); 61 dest.writeParcelable(mDataNotificationConfig, flags); 62 dest.writeBoolean(mIsAngleOfArrivalNeeded); 63 dest.writeInt(mRangingMeasurementsLimit); 64 } 65 66 @Override describeContents()67 public int describeContents() { 68 return 0; 69 } 70 71 @NonNull 72 public static final Creator<SessionConfig> CREATOR = 73 new Creator<SessionConfig>() { 74 @Override 75 public SessionConfig createFromParcel(Parcel in) { 76 return new SessionConfig(in); 77 } 78 79 @Override 80 public SessionConfig[] newArray(int size) { 81 return new SessionConfig[size]; 82 } 83 }; 84 85 /** 86 * Returns the sensor fusion parameters used for this preference. 87 * 88 * @return a non-null {@link SensorFusionParams} instance. 89 */ 90 @NonNull getSensorFusionParams()91 public SensorFusionParams getSensorFusionParams() { 92 return mFusionParams; 93 } 94 95 /** 96 * Returns the data notification configuration for this preference. 97 * 98 * @return a non-null {@link DataNotificationConfig} instance. 99 */ 100 @NonNull getDataNotificationConfig()101 public DataNotificationConfig getDataNotificationConfig() { 102 return mDataNotificationConfig; 103 } 104 105 /** 106 * Returns whether Angle-of-arrival was requested by the app. 107 */ isAngleOfArrivalNeeded()108 public boolean isAngleOfArrivalNeeded() { 109 return mIsAngleOfArrivalNeeded; 110 } 111 112 /** 113 * Returns the configured ranging measurements limit for the ranging session. 114 */ 115 @IntRange(from = 0, to = 65535) getRangingMeasurementsLimit()116 public int getRangingMeasurementsLimit() { 117 return mRangingMeasurementsLimit; 118 } 119 120 /** 121 * Builder for creating instances of {@link SessionConfig}. 122 */ 123 public static final class Builder { 124 private DataNotificationConfig mDataNotificationConfig = 125 new DataNotificationConfig.Builder().build(); 126 private SensorFusionParams mFusionParams = new SensorFusionParams.Builder().build(); 127 private boolean mIsAngleOfArrivalNeeded = false; 128 private int mRangingMeasurementsLimit = 0; 129 130 /** 131 * Sets the sensor fusion parameters for this preference. 132 * 133 * @param parameters the {@link SensorFusionParams} to use. 134 * @return the builder instance. 135 * @throws IllegalArgumentException if the parameters is null. 136 */ 137 @NonNull setSensorFusionParams( @onNull SensorFusionParams parameters)138 public Builder setSensorFusionParams( 139 @NonNull SensorFusionParams parameters) { 140 mFusionParams = parameters; 141 return this; 142 } 143 144 /** 145 * Sets the data notification configuration for this preference. 146 * 147 * @param config the {@link DataNotificationConfig} to use. 148 * @return the builder instance for chaining. 149 * @throws IllegalArgumentException if the config is null. 150 */ 151 @NonNull setDataNotificationConfig( @onNull DataNotificationConfig config)152 public Builder setDataNotificationConfig( 153 @NonNull DataNotificationConfig config) { 154 mDataNotificationConfig = config; 155 return this; 156 } 157 158 /** 159 * Sets whether Angle of Arrival (AoA) is required for the ranging operation. 160 * 161 * <p> Defaults to false 162 * 163 * @param isAngleOfArrivalNeeded {@code true} if AoA data is required; {@code false} 164 * otherwise. 165 * @return The {@link Builder} instance. 166 */ 167 @NonNull setAngleOfArrivalNeeded(boolean isAngleOfArrivalNeeded)168 public Builder setAngleOfArrivalNeeded(boolean isAngleOfArrivalNeeded) { 169 mIsAngleOfArrivalNeeded = isAngleOfArrivalNeeded; 170 return this; 171 } 172 173 /** 174 * Sets the maximum number of ranging rounds for this session. This includes all ranging 175 * rounds, irrespective of whether they were successful or not. For 1:many sessions, a round 176 * includes ranging to all peers within that round. 177 * 178 * <p> By default, when the value is set to {@code 0}, the ranging session will run 179 * indefinitely. 180 * 181 * @param rangingMeasurementsLimit the maximum number of ranging rounds (0 to 65535). 182 * @return this {@link Builder} instance. 183 * @throws IllegalArgumentException if the value is outside the allowed range (0 to 65535). 184 */ 185 @NonNull setRangingMeasurementsLimit( @ntRangefrom = 0, to = 65535) int rangingMeasurementsLimit)186 public Builder setRangingMeasurementsLimit( 187 @IntRange(from = 0, to = 65535) int rangingMeasurementsLimit) { 188 if (rangingMeasurementsLimit < 0 189 || rangingMeasurementsLimit > 65535) { 190 throw new IllegalArgumentException( 191 "Ranging measurements limit must be between 0 and 65535"); 192 } 193 mRangingMeasurementsLimit = rangingMeasurementsLimit; 194 return this; 195 } 196 197 /** 198 * Builds a new {@link SessionConfig} instance. 199 * 200 * @return the new {@link SessionConfig} instance. 201 */ 202 @NonNull build()203 public SessionConfig build() { 204 return new SessionConfig(this); 205 } 206 } 207 208 @Override toString()209 public String toString() { 210 return "SessionConfig{" 211 + "mFusionParams=" 212 + mFusionParams 213 + ", mDataNotificationConfig=" 214 + mDataNotificationConfig 215 + ", mIsAngleOfArrivalNeeded=" 216 + mIsAngleOfArrivalNeeded 217 + ", mRangingMeasurementsLimit=" 218 + mRangingMeasurementsLimit 219 + "}"; 220 } 221 222 /** 223 * @hide 224 */ 225 @Override equals(Object o)226 public boolean equals(Object o) { 227 if (this == o) return true; 228 if (!(o instanceof SessionConfig that)) return false; 229 return mIsAngleOfArrivalNeeded == that.mIsAngleOfArrivalNeeded 230 && mRangingMeasurementsLimit == that.mRangingMeasurementsLimit 231 && Objects.equals(mFusionParams, that.mFusionParams) 232 && Objects.equals(mDataNotificationConfig, that.mDataNotificationConfig); 233 } 234 235 /** 236 * @hide 237 */ 238 @Override hashCode()239 public int hashCode() { 240 return Objects.hash(mFusionParams, mDataNotificationConfig, mIsAngleOfArrivalNeeded, 241 mRangingMeasurementsLimit); 242 } 243 } 244