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