1 /*
2  * Copyright (C) 2021 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 package com.android.server.uwb;
17 
18 import android.os.PersistableBundle;
19 import android.uwb.RangingChangeReason;
20 
21 import com.android.server.uwb.data.UwbUciConstants;
22 
23 import com.google.uwb.support.aliro.AliroParams;
24 import com.google.uwb.support.aliro.AliroRangingError;
25 import com.google.uwb.support.base.Params;
26 import com.google.uwb.support.ccc.CccParams;
27 import com.google.uwb.support.ccc.CccRangingError;
28 import com.google.uwb.support.fira.FiraStatusCode;
29 
30 public class UwbSessionNotificationHelper {
convertUciReasonCodeToApiReasonCode(int reasonCode)31     public static int convertUciReasonCodeToApiReasonCode(int reasonCode) {
32         /* set default */
33         int rangingChangeReason = RangingChangeReason.UNKNOWN;
34         switch (reasonCode) {
35             case UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS:
36                 rangingChangeReason = RangingChangeReason.LOCAL_API;
37                 break;
38             case UwbUciConstants.REASON_MAX_RANGING_ROUND_RETRY_COUNT_REACHED:
39                 rangingChangeReason = RangingChangeReason.MAX_RR_RETRY_REACHED;
40                 break;
41             case UwbUciConstants.REASON_MAX_NUMBER_OF_MEASUREMENTS_REACHED:
42                 rangingChangeReason = RangingChangeReason.REMOTE_REQUEST;
43                 break;
44             case UwbUciConstants.REASON_ERROR_INSUFFICIENT_SLOTS_PER_RR:
45             case UwbUciConstants.REASON_ERROR_SLOT_LENGTH_NOT_SUPPORTED:
46             case UwbUciConstants.REASON_ERROR_INVALID_UL_TDOA_RANDOM_WINDOW:
47             case UwbUciConstants.REASON_ERROR_MAC_ADDRESS_MODE_NOT_SUPPORTED:
48             case UwbUciConstants.REASON_ERROR_INVALID_RANGING_INTERVAL:
49             case UwbUciConstants.REASON_ERROR_INVALID_STS_CONFIG:
50             case UwbUciConstants.REASON_ERROR_INVALID_RFRAME_CONFIG:
51             case UwbUciConstants.REASON_ERROR_HUS_NOT_ENOUGH_SLOTS:
52             case UwbUciConstants.REASON_ERROR_HUS_CFP_PHASE_TOO_SHORT:
53             case UwbUciConstants.REASON_ERROR_HUS_CAP_PHASE_TOO_SHORT:
54             case UwbUciConstants.REASON_ERROR_HUS_OTHERS:
55                 rangingChangeReason = RangingChangeReason.BAD_PARAMETERS;
56                 break;
57             case UwbUciConstants.REASON_ERROR_SESSION_KEY_NOT_FOUND:
58             case UwbUciConstants.REASON_ERROR_SUB_SESSION_KEY_NOT_FOUND:
59                 rangingChangeReason = RangingChangeReason.PROTOCOL_SPECIFIC;
60                 break;
61             case UwbUciConstants.REASON_REGULATION_UWB_OFF:
62                 rangingChangeReason = RangingChangeReason.SYSTEM_REGULATION;
63                 break;
64             case UwbUciConstants.REASON_SESSION_RESUMED_DUE_TO_INBAND_SIGNAL:
65                 rangingChangeReason = RangingChangeReason.SESSION_RESUMED;
66                 break;
67             case UwbUciConstants.REASON_SESSION_SUSPENDED_DUE_TO_INBAND_SIGNAL:
68                 rangingChangeReason = RangingChangeReason.SESSION_SUSPENDED;
69                 break;
70             case UwbUciConstants.REASON_SESSION_STOPPED_DUE_TO_INBAND_SIGNAL:
71                 rangingChangeReason = RangingChangeReason.INBAND_SESSION_STOP;
72                 break;
73         }
74         return rangingChangeReason;
75     }
76 
convertUciStatusToApiReasonCode(int status)77     public static int convertUciStatusToApiReasonCode(int status) {
78         /* set default */
79         int rangingChangeReason = RangingChangeReason.UNKNOWN;
80         switch (status) {
81             case UwbUciConstants.STATUS_CODE_OK:
82                 rangingChangeReason = RangingChangeReason.LOCAL_API;
83                 break;
84             case UwbUciConstants.STATUS_CODE_ERROR_MAX_SESSIONS_EXCEEDED:
85                 rangingChangeReason = RangingChangeReason.MAX_SESSIONS_REACHED;
86                 break;
87             case UwbUciConstants.STATUS_CODE_INVALID_PARAM:
88             case UwbUciConstants.STATUS_CODE_INVALID_RANGE:
89             case UwbUciConstants.STATUS_CODE_INVALID_MESSAGE_SIZE:
90                 rangingChangeReason = RangingChangeReason.BAD_PARAMETERS;
91                 break;
92             case UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST:
93             case UwbUciConstants.STATUS_CODE_CCC_LIFECYCLE:
94             case UwbUciConstants.STATUS_CODE_CCC_SE_BUSY:
95                 rangingChangeReason = RangingChangeReason.PROTOCOL_SPECIFIC;
96                 break;
97             case UwbUciConstants.REASON_ERROR_INSUFFICIENT_SLOTS_PER_RR:
98                 rangingChangeReason = RangingChangeReason.INSUFFICIENT_SLOTS_PER_RR;
99                 break;
100         }
101         return rangingChangeReason;
102     }
103 
104     /**
105      * Convert UCI status code received in SESSION_DATA_TRANSFER_PHASE_CONFIGURATION_NTF to
106      * an API reason code.
107      */
convertDataTransferPhaseConfigStatusToApiReasonCode( int dataTransferPhaseConfigStatus)108     public static int convertDataTransferPhaseConfigStatusToApiReasonCode(
109             int dataTransferPhaseConfigStatus) {
110         int rangingChangeReason = RangingChangeReason.UNKNOWN;
111         switch (dataTransferPhaseConfigStatus) {
112             case UwbUciConstants.STATUS_CODE_DATA_TRANSFER_PHASE_CONFIG_DTPCM_CONFIG_SUCCESS:
113                 rangingChangeReason = RangingChangeReason.LOCAL_API;
114                 break;
115             case UwbUciConstants.STATUS_CODE_DATA_TRANSFER_PHASE_CONFIG_ERROR_DUPLICATE_SLOT_ASSIGNMENT:
116                 rangingChangeReason = RangingChangeReason.PROTOCOL_SPECIFIC;
117                 break;
118         }
119         return rangingChangeReason;
120     }
121 
122     /**
123      * Convert UCI reason code values to UCI status code, as some of the callbacks expect to get
124      * the latter.
125      */
convertUciReasonCodeToUciStatusCode(int reasonCode)126     public static int convertUciReasonCodeToUciStatusCode(int reasonCode) {
127         int statusCode = UwbUciConstants.STATUS_CODE_FAILED;
128         switch (reasonCode) {
129             case UwbUciConstants.REASON_STATE_CHANGE_WITH_SESSION_MANAGEMENT_COMMANDS:
130                 statusCode = UwbUciConstants.STATUS_CODE_OK;
131                 break;
132             case UwbUciConstants.REASON_ERROR_SESSION_KEY_NOT_FOUND:
133             case UwbUciConstants.REASON_ERROR_SUB_SESSION_KEY_NOT_FOUND:
134                 statusCode = UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST;
135                 break;
136         }
137         return statusCode;
138     }
139 
convertUciStatusToApiCccProtocolError(int status)140     private static @CccParams.ProtocolError int convertUciStatusToApiCccProtocolError(int status) {
141         switch (status) {
142             case UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST:
143                 return CccParams.PROTOCOL_ERROR_NOT_FOUND;
144             case UwbUciConstants.STATUS_CODE_CCC_LIFECYCLE:
145                 return CccParams.PROTOCOL_ERROR_LIFECYCLE;
146             case UwbUciConstants.STATUS_CODE_CCC_SE_BUSY:
147                 return CccParams.PROTOCOL_ERROR_SE_BUSY;
148             default:
149                 return CccParams.PROTOCOL_ERROR_UNKNOWN;
150         }
151     }
152 
convertUciStatusToApiAliroProtocolError( int status)153     private static @AliroParams.ProtocolError int convertUciStatusToApiAliroProtocolError(
154             int status) {
155         switch (status) {
156             case UwbUciConstants.STATUS_CODE_ERROR_SESSION_NOT_EXIST:
157                 return AliroParams.PROTOCOL_ERROR_NOT_FOUND;
158             default:
159                 return AliroParams.PROTOCOL_ERROR_UNKNOWN;
160         }
161     }
162 
convertUciStatusToParam(String protocolName, int status)163     public static PersistableBundle convertUciStatusToParam(String protocolName, int status) {
164         Params c;
165         if (protocolName.equals(CccParams.PROTOCOL_NAME)) {
166             c = new CccRangingError.Builder()
167                     .setError(convertUciStatusToApiCccProtocolError(status))
168                     .build();
169         } else if (protocolName.equals(AliroParams.PROTOCOL_NAME)) {
170             c = new AliroRangingError.Builder()
171                     .setError(convertUciStatusToApiAliroProtocolError(status))
172                     .build();
173         } else {
174             c = new FiraStatusCode.Builder().setStatusCode(status).build();
175         }
176         return c.toBundle();
177     }
178 
getSessionStateString(int state)179     static String getSessionStateString(int state) {
180         String ret = "";
181         switch (state) {
182             case UwbUciConstants.UWB_SESSION_STATE_INIT:
183                 ret = "INIT";
184                 break;
185             case UwbUciConstants.UWB_SESSION_STATE_DEINIT:
186                 ret = "DEINIT";
187                 break;
188             case UwbUciConstants.UWB_SESSION_STATE_ACTIVE:
189                 ret = "ACTIVE";
190                 break;
191             case UwbUciConstants.UWB_SESSION_STATE_IDLE:
192                 ret = "IDLE";
193                 break;
194             case UwbUciConstants.UWB_SESSION_STATE_ERROR:
195                 ret = "ERROR";
196                 break;
197         }
198         return ret;
199     }
200 }
201