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 SessionInfo(AttributionSource attributionSource, SessionHandle sessionHandle, ServiceProfileInfo serviceProfileInfo, Context context, IUwbRangingCallbacks rangingCallbacks, String chipId)223 public SessionInfo(AttributionSource attributionSource, SessionHandle sessionHandle, 224 ServiceProfileInfo serviceProfileInfo, 225 Context context, 226 IUwbRangingCallbacks rangingCallbacks, 227 String chipId) { 228 mAttributionSource = attributionSource; 229 mSessionHandle = sessionHandle; 230 service_instance_id = serviceProfileInfo.serviceInstanceID; 231 mServiceProfileInfo = serviceProfileInfo; 232 mContext = context; 233 mRangingCallbacks = rangingCallbacks; 234 mDestAddressList = new ArrayList<>(); 235 subSessionId = Optional.empty(); 236 mChipId = chipId; 237 } 238 getSessionId()239 public int getSessionId() { 240 return mSessionId; 241 } 242 getDeviceAddress()243 public UwbAddress getDeviceAddress() { 244 return mDeviceAddress; 245 } 246 setSessionId(int sessionID)247 public void setSessionId(int sessionID) { 248 mSessionId = sessionID; 249 } 250 setUwbAddress(UwbAddress uwbAddress)251 public void setUwbAddress(UwbAddress uwbAddress) { 252 mDeviceAddress = uwbAddress; 253 } 254 setSubSessionId(int subSessionId)255 public void setSubSessionId(int subSessionId) { 256 this.subSessionId = Optional.of(subSessionId); 257 } 258 259 /** Gets the session key info, required for controller of multicast case. */ 260 @NonNull getSharedSessionKeyInfo()261 public byte[] getSharedSessionKeyInfo() { 262 if (mSharedSessionKeyInfo.isEmpty()) { 263 // only set once, as it is shared by all sub sessions. 264 mSharedSessionKeyInfo = Optional.of(CsmlUtil.generate256BitRandomKeyInfo()); 265 } 266 return mSharedSessionKeyInfo.get(); 267 } 268 } 269 } 270