1 /* 2 * Copyright (C) 2022 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.uwb.pm; 18 19 import android.annotation.NonNull; 20 import android.content.AttributionSource; 21 import android.content.Context; 22 import android.os.Handler; 23 import android.os.RemoteException; 24 import android.uwb.IUwbRangingCallbacks; 25 import android.uwb.SessionHandle; 26 import android.uwb.UwbAddress; 27 28 import com.android.internal.util.State; 29 import com.android.internal.util.StateMachine; 30 import com.android.server.uwb.UwbInjector; 31 import com.android.server.uwb.UwbServiceCore; 32 import com.android.server.uwb.data.ServiceProfileData.ServiceProfileInfo; 33 import com.android.server.uwb.data.UwbConfig; 34 import com.android.server.uwb.secure.csml.CsmlUtil; 35 import com.android.server.uwb.secure.csml.SessionData; 36 37 import com.google.uwb.support.fira.FiraOpenSessionParams; 38 import com.google.uwb.support.generic.GenericSpecificationParams; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.Optional; 43 import java.util.UUID; 44 45 /** 46 * Abstract class for session with profiles 47 */ 48 public abstract class RangingSessionController extends StateMachine { 49 public static String TAG = "RangingSessionController"; 50 51 public SessionInfo mSessionInfo; 52 public Handler mHandler; 53 public UwbInjector mUwbInjector; 54 private GenericSpecificationParams mSpecificationParams; 55 protected boolean mVerboseLoggingEnabled = false; 56 57 protected State mIdleState = null; 58 protected State mDiscoveryState = null; 59 protected State mTransportState = null; 60 protected State mSecureSessionState = null; 61 protected State mRangingState = null; 62 protected State mEndSessionState = null; 63 64 public static final int SESSION_INITIALIZED = 1; 65 public static final int SESSION_START = 2; 66 public static final int SESSION_STOP = 3; 67 68 public static final int DISCOVERY_INIT = 101; 69 public static final int DISCOVERY_STARTED = 102; 70 public static final int DISCOVERY_SUCCESS = 103; 71 public static final int DISCOVERY_ENDED = 104; 72 public static final int DISCOVERY_FAILED = 105; 73 74 public static final int TRANSPORT_INIT = 201; 75 public static final int TRANSPORT_STARTED = 202; 76 public static final int TRANSPORT_COMPLETED = 203; 77 public static final int TRANSPORT_FAILURE = 204; 78 79 public static final int SECURE_SESSION_INIT = 301; 80 public static final int SECURE_SESSION_ESTABLISHED = 302; 81 public static final int SECURE_SESSION_FAILURE = 303; 82 83 public static final int RANGING_INIT = 401; 84 public static final int RANGING_OPENED = 402; 85 public static final int RANGING_STARTED = 403; 86 public static final int RANGING_FAILURE = 404; 87 public static final int RANGING_ENDED = 405; 88 RangingSessionController(SessionHandle sessionHandle, AttributionSource attributionSource, Context context, UwbInjector uwbInjector, ServiceProfileInfo serviceProfileInfo, IUwbRangingCallbacks rangingCallbacks, Handler handler, String chipId)89 public RangingSessionController(SessionHandle sessionHandle, 90 AttributionSource attributionSource, 91 Context context, 92 UwbInjector uwbInjector, 93 ServiceProfileInfo serviceProfileInfo, 94 IUwbRangingCallbacks rangingCallbacks, 95 Handler handler, 96 String chipId) { 97 super("RangingSessionController", handler); 98 99 mSessionInfo = new SessionInfo(attributionSource, sessionHandle, 100 serviceProfileInfo, context, rangingCallbacks, chipId); 101 102 mIdleState = getIdleState(); 103 mDiscoveryState = getDiscoveryState(); 104 mTransportState = getTransportState(); 105 mSecureSessionState = getSecureState(); 106 mRangingState = getRangingState(); 107 mEndSessionState = getEndingState(); 108 109 mUwbInjector = uwbInjector; 110 mHandler = handler; 111 112 addState(mIdleState); 113 addState(mDiscoveryState); 114 { 115 addState(mTransportState, mDiscoveryState); 116 { 117 addState(mSecureSessionState, mTransportState); 118 { 119 addState(mRangingState, mSecureSessionState); 120 } 121 } 122 } 123 addState(mEndSessionState); 124 125 setInitialState(mIdleState); 126 127 start(); 128 129 sendMessage(SESSION_INITIALIZED); 130 } 131 132 /** States need to be implemented by profiles */ getIdleState()133 public abstract State getIdleState(); 134 getDiscoveryState()135 public abstract State getDiscoveryState(); 136 getTransportState()137 public abstract State getTransportState(); 138 getSecureState()139 public abstract State getSecureState(); 140 getRangingState()141 public abstract State getRangingState(); 142 getEndingState()143 public abstract State getEndingState(); 144 enableVerboseLogging(boolean verbose)145 public void enableVerboseLogging(boolean verbose) { 146 mVerboseLoggingEnabled = verbose; 147 } 148 startSession()149 public void startSession() { 150 sendMessage(SESSION_START); 151 } 152 stopSession()153 public void stopSession() { 154 sendMessage(SESSION_STOP); 155 } 156 closeSession()157 public void closeSession() { 158 sendMessage(RANGING_ENDED); 159 } 160 getUwbConfig()161 public abstract UwbConfig getUwbConfig(); 162 openRangingSession()163 public void openRangingSession() throws RemoteException { 164 165 FiraOpenSessionParams firaOpenSessionParams = 166 UwbConfig.getOpenSessionParams(mSessionInfo, getUwbConfig()); 167 168 UwbServiceCore uwbServiceCore = mUwbInjector.getUwbServiceCore(); 169 170 uwbServiceCore.openRanging( 171 mSessionInfo.mAttributionSource, 172 mSessionInfo.mSessionHandle, 173 mSessionInfo.mRangingCallbacks, 174 firaOpenSessionParams.toBundle(), 175 mUwbInjector.getMultichipData().getDefaultChipId() 176 ); 177 sendMessage(RANGING_OPENED); 178 } 179 startRanging()180 protected void startRanging() { 181 FiraOpenSessionParams firaOpenSessionParams = 182 UwbConfig.getOpenSessionParams(mSessionInfo, getUwbConfig()); 183 mUwbInjector.getUwbServiceCore().startRanging(mSessionInfo.mSessionHandle, 184 firaOpenSessionParams.toBundle()); 185 sendMessage(RANGING_STARTED); 186 } 187 stopRanging()188 protected void stopRanging() { 189 mUwbInjector.getUwbServiceCore().stopRanging(mSessionInfo.mSessionHandle); 190 } 191 closeRanging()192 protected void closeRanging() { 193 mUwbInjector.getUwbServiceCore().closeRanging(mSessionInfo.mSessionHandle); 194 } 195 getSpecificationInfo()196 protected GenericSpecificationParams getSpecificationInfo() { 197 if (mSpecificationParams == null) { 198 mSpecificationParams = 199 mUwbInjector.getUwbServiceCore().getCachedSpecificationParams( 200 mSessionInfo.mChipId); 201 } 202 return mSpecificationParams; 203 } 204 205 /** 206 * Holds all session related information 207 */ 208 public static class SessionInfo { 209 public final AttributionSource mAttributionSource; 210 public final SessionHandle mSessionHandle; 211 public final Context mContext; 212 public final UUID service_instance_id; 213 public ServiceProfileInfo mServiceProfileInfo; 214 private int mSessionId; 215 public IUwbRangingCallbacks mRangingCallbacks; 216 private UwbAddress mDeviceAddress; 217 public final List<UwbAddress> mDestAddressList; 218 public Optional<Integer> subSessionId; 219 public final String mChipId; 220 public SessionData mSessionData; 221 private Optional<byte[]> mSharedSessionKeyInfo = Optional.empty(); 222 public Optional<byte[]> mSubSessionKey = Optional.empty(); 223 public Optional<byte[]> mSessionKey = Optional.empty(); 224 SessionInfo(AttributionSource attributionSource, SessionHandle sessionHandle, ServiceProfileInfo serviceProfileInfo, Context context, IUwbRangingCallbacks rangingCallbacks, String chipId)225 public SessionInfo(AttributionSource attributionSource, SessionHandle sessionHandle, 226 ServiceProfileInfo serviceProfileInfo, 227 Context context, 228 IUwbRangingCallbacks rangingCallbacks, 229 String chipId) { 230 mAttributionSource = attributionSource; 231 mSessionHandle = sessionHandle; 232 service_instance_id = serviceProfileInfo.serviceInstanceID; 233 mServiceProfileInfo = serviceProfileInfo; 234 mContext = context; 235 mRangingCallbacks = rangingCallbacks; 236 mDestAddressList = new ArrayList<>(); 237 subSessionId = Optional.empty(); 238 mChipId = chipId; 239 } 240 getSessionId()241 public int getSessionId() { 242 return mSessionId; 243 } 244 getDeviceAddress()245 public UwbAddress getDeviceAddress() { 246 return mDeviceAddress; 247 } 248 setSessionId(int sessionID)249 public void setSessionId(int sessionID) { 250 mSessionId = sessionID; 251 } 252 setUwbAddress(UwbAddress uwbAddress)253 public void setUwbAddress(UwbAddress uwbAddress) { 254 mDeviceAddress = uwbAddress; 255 } 256 setSubSessionId(int subSessionId)257 public void setSubSessionId(int subSessionId) { 258 this.subSessionId = Optional.of(subSessionId); 259 } 260 setSubSessionKey(byte[] subSessionKey)261 public void setSubSessionKey(byte[] subSessionKey) { 262 this.mSubSessionKey = Optional.of(subSessionKey); 263 } 264 setSessionKey(byte[] sessionKey)265 public void setSessionKey(byte[] sessionKey) { 266 this.mSessionKey = Optional.of(sessionKey); 267 } 268 /** Gets the session key info, required for controller of multicast case. */ 269 @NonNull getSharedSessionKeyInfo()270 public byte[] getSharedSessionKeyInfo() { 271 if (mSharedSessionKeyInfo.isEmpty()) { 272 // only set once, as it is shared by all sub sessions. 273 mSharedSessionKeyInfo = Optional.of(CsmlUtil.generate256BitRandomKeyInfo()); 274 } 275 return mSharedSessionKeyInfo.get(); 276 } 277 } 278 } 279