1 /* 2 * Copyright (C) 2023 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.internal.telephony.satellite.metrics; 18 19 import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID; 20 import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE; 21 import static android.telephony.satellite.SatelliteManager.KEY_SESSION_STATS_V2; 22 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS; 23 24 import android.annotation.NonNull; 25 import android.os.Bundle; 26 import android.os.ResultReceiver; 27 import android.telephony.satellite.NtnSignalStrength; 28 import android.telephony.satellite.SatelliteManager; 29 import android.telephony.satellite.SatelliteSessionStats; 30 import android.util.Log; 31 32 import com.android.internal.telephony.metrics.SatelliteStats; 33 import com.android.internal.telephony.satellite.DatagramDispatcher; 34 35 /** 36 * Stats to log to satellite session metrics 37 */ 38 public class SessionMetricsStats { 39 private static final String TAG = SessionMetricsStats.class.getSimpleName(); 40 41 private static SessionMetricsStats sInstance = null; 42 private @SatelliteManager.SatelliteResult int mInitializationResult; 43 private @SatelliteManager.NTRadioTechnology int mRadioTechnology; 44 private @SatelliteManager.SatelliteResult int mTerminationResult; 45 private long mInitializationProcessingTimeMillis; 46 private long mTerminationProcessingTimeMillis; 47 private int mSessionDurationSec; 48 private int mCountOfSuccessfulOutgoingDatagram; 49 private int mShadowCountOfSuccessfulOutgoingDatagram; 50 private int mCountOfFailedOutgoingDatagram; 51 private int mShadowCountOfFailedOutgoingDatagram; 52 private int mCountOfTimedOutUserMessagesWaitingForConnection; 53 private int mShadowCountOfTimedOutUserMessagesWaitingForConnection; 54 private int mCountOfTimedOutUserMessagesWaitingForAck; 55 private int mShadowCountOfTimedOutUserMessagesWaitingForAck; 56 private int mCountOfSuccessfulIncomingDatagram; 57 private int mCountOfIncomingDatagramFailed; 58 private boolean mIsDemoMode; 59 private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel; 60 private int mCarrierId; 61 private int mCountOfSatelliteNotificationDisplayed; 62 private int mCountOfAutoExitDueToScreenOff; 63 private int mCountOfAutoExitDueToTnNetwork; 64 private boolean mIsEmergency; 65 private boolean mIsNtnOnlyCarrier; 66 private int mMaxInactivityDurationSec; 67 private SatelliteSessionStats mDatagramStats; 68 SessionMetricsStats()69 private SessionMetricsStats() { 70 initializeSessionMetricsParam(); 71 mDatagramStats = new SatelliteSessionStats(); 72 } 73 74 /** 75 * Returns the Singleton instance of SessionMetricsStats class. 76 * If an instance of the Singleton class has not been created, 77 * it creates a new instance and returns it. Otherwise, it returns 78 * the existing instance. 79 * @return the Singleton instance of SessionMetricsStats. 80 */ getInstance()81 public static SessionMetricsStats getInstance() { 82 if (sInstance == null) { 83 loge("create new SessionMetricsStats."); 84 sInstance = new SessionMetricsStats(); 85 } 86 return sInstance; 87 } 88 89 /** Sets the satellite initialization result. */ setInitializationResult( @atelliteManager.SatelliteResult int result)90 public SessionMetricsStats setInitializationResult( 91 @SatelliteManager.SatelliteResult int result) { 92 logd("setInitializationResult(" + result + ")"); 93 mInitializationResult = result; 94 return this; 95 } 96 97 /** Sets the satellite ratio technology. */ setSatelliteTechnology( @atelliteManager.NTRadioTechnology int radioTechnology)98 public SessionMetricsStats setSatelliteTechnology( 99 @SatelliteManager.NTRadioTechnology int radioTechnology) { 100 logd("setSatelliteTechnology(" + radioTechnology + ")"); 101 mRadioTechnology = radioTechnology; 102 return this; 103 } 104 105 /** Sets the satellite de-initialization result. */ setTerminationResult( @atelliteManager.SatelliteResult int result)106 public SessionMetricsStats setTerminationResult( 107 @SatelliteManager.SatelliteResult int result) { 108 logd("setTerminationResult(" + result + ")"); 109 mTerminationResult = result; 110 return this; 111 } 112 113 /** Sets the satellite initialization processing time. */ setInitializationProcessingTime(long processingTime)114 public SessionMetricsStats setInitializationProcessingTime(long processingTime) { 115 logd("setInitializationProcessingTime(" + processingTime + ")"); 116 mInitializationProcessingTimeMillis = processingTime; 117 return this; 118 } 119 120 /** Sets the satellite de-initialization processing time. */ setTerminationProcessingTime(long processingTime)121 public SessionMetricsStats setTerminationProcessingTime(long processingTime) { 122 logd("setTerminationProcessingTime(" + processingTime + ")"); 123 mTerminationProcessingTimeMillis = processingTime; 124 return this; 125 } 126 127 /** Sets the total enabled time for the satellite session. */ setSessionDurationSec(int sessionDurationSec)128 public SessionMetricsStats setSessionDurationSec(int sessionDurationSec) { 129 logd("setSessionDuration(" + sessionDurationSec + ")"); 130 mSessionDurationSec = sessionDurationSec; 131 return this; 132 } 133 134 /** Increase the count of successful outgoing datagram transmission. */ addCountOfSuccessfulOutgoingDatagram( @onNull @atelliteManager.DatagramType int datagramType, long datagramTransmissionTime)135 public SessionMetricsStats addCountOfSuccessfulOutgoingDatagram( 136 @NonNull @SatelliteManager.DatagramType int datagramType, 137 long datagramTransmissionTime) { 138 logd("addCountOfSuccessfulOutgoingDatagram: datagramType=" + datagramType); 139 mDatagramStats.recordSuccessfulOutgoingDatagramStats(datagramType, 140 datagramTransmissionTime); 141 if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) { 142 // Ignore KEEP_ALIVE messages 143 return this; 144 } 145 146 mCountOfSuccessfulOutgoingDatagram++; 147 mShadowCountOfSuccessfulOutgoingDatagram++; 148 return this; 149 } 150 151 /** Increase the count of failed outgoing datagram transmission. */ addCountOfFailedOutgoingDatagram( @onNull @atelliteManager.DatagramType int datagramType, @NonNull @SatelliteManager.SatelliteResult int resultCode)152 public SessionMetricsStats addCountOfFailedOutgoingDatagram( 153 @NonNull @SatelliteManager.DatagramType int datagramType, 154 @NonNull @SatelliteManager.SatelliteResult int resultCode) { 155 logd("addCountOfFailedOutgoingDatagram: datagramType=" + datagramType + " resultCode = " 156 + resultCode); 157 mDatagramStats.addCountOfUnsuccessfulUserMessages(datagramType, resultCode); 158 if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) { 159 // Ignore KEEP_ALIVE messages 160 return this; 161 } 162 163 mCountOfFailedOutgoingDatagram++; 164 mShadowCountOfFailedOutgoingDatagram++; 165 if (resultCode == SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE) { 166 addCountOfTimedOutUserMessagesWaitingForConnection(datagramType); 167 } else if (resultCode == SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT) { 168 addCountOfTimedOutUserMessagesWaitingForAck(datagramType); 169 } 170 return this; 171 } 172 173 /** Increase the count of user messages that timed out waiting for connection. */ addCountOfTimedOutUserMessagesWaitingForConnection( @onNull @atelliteManager.DatagramType int datagramType)174 private SessionMetricsStats addCountOfTimedOutUserMessagesWaitingForConnection( 175 @NonNull @SatelliteManager.DatagramType int datagramType) { 176 if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) { 177 // Ignore KEEP_ALIVE messages 178 return this; 179 } 180 181 mCountOfTimedOutUserMessagesWaitingForConnection++; 182 mShadowCountOfTimedOutUserMessagesWaitingForConnection++; 183 logd("addCountOfTimedOutUserMessagesWaitingForConnection: current count=" 184 + mCountOfTimedOutUserMessagesWaitingForConnection); 185 return this; 186 } 187 188 /** Increase the count of user messages that timed out waiting for ack. */ addCountOfTimedOutUserMessagesWaitingForAck( @onNull @atelliteManager.DatagramType int datagramType)189 private SessionMetricsStats addCountOfTimedOutUserMessagesWaitingForAck( 190 @NonNull @SatelliteManager.DatagramType int datagramType) { 191 if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) { 192 // Ignore KEEP_ALIVE messages 193 return this; 194 } 195 196 mCountOfTimedOutUserMessagesWaitingForAck++; 197 mShadowCountOfTimedOutUserMessagesWaitingForAck++; 198 logd("addCountOfTimedOutUserMessagesWaitingForAck: current count=" 199 + mCountOfTimedOutUserMessagesWaitingForAck); 200 return this; 201 } 202 203 /** Increase the count of successful incoming datagram transmission. */ addCountOfSuccessfulIncomingDatagram()204 public SessionMetricsStats addCountOfSuccessfulIncomingDatagram() { 205 mCountOfSuccessfulIncomingDatagram++; 206 logd("addCountOfSuccessfulIncomingDatagram: current count=" 207 + mCountOfSuccessfulIncomingDatagram); 208 return this; 209 } 210 211 /** Increase the count of failed incoming datagram transmission. */ addCountOfFailedIncomingDatagram()212 public SessionMetricsStats addCountOfFailedIncomingDatagram() { 213 mCountOfIncomingDatagramFailed++; 214 logd("addCountOfFailedIncomingDatagram: current count=" + mCountOfIncomingDatagramFailed); 215 return this; 216 } 217 218 /** Sets whether the session is enabled for demo mode or not. */ setIsDemoMode(boolean isDemoMode)219 public SessionMetricsStats setIsDemoMode(boolean isDemoMode) { 220 mIsDemoMode = isDemoMode; 221 logd("setIsDemoMode(" + mIsDemoMode + ")"); 222 return this; 223 } 224 225 /** Updates the max Ntn signal strength level for the session. */ updateMaxNtnSignalStrengthLevel( @tnSignalStrength.NtnSignalStrengthLevel int latestNtnSignalStrengthLevel)226 public SessionMetricsStats updateMaxNtnSignalStrengthLevel( 227 @NtnSignalStrength.NtnSignalStrengthLevel int latestNtnSignalStrengthLevel) { 228 if (latestNtnSignalStrengthLevel > mMaxNtnSignalStrengthLevel) { 229 mMaxNtnSignalStrengthLevel = latestNtnSignalStrengthLevel; 230 } 231 logd("updateMaxNtnSignalsStrength: latest signal strength=" + latestNtnSignalStrengthLevel 232 + ", max signal strength=" + mMaxNtnSignalStrengthLevel); 233 return this; 234 } 235 236 /** Sets the Carrier ID of this NTN session. */ setCarrierId(int carrierId)237 public SessionMetricsStats setCarrierId(int carrierId) { 238 mCarrierId = carrierId; 239 logd("setCarrierId(" + carrierId + ")"); 240 return this; 241 } 242 243 /** Increase the count of Satellite Notification Display. */ addCountOfSatelliteNotificationDisplayed()244 public SessionMetricsStats addCountOfSatelliteNotificationDisplayed() { 245 mCountOfSatelliteNotificationDisplayed++; 246 logd("addCountOfSatelliteNotificationDisplayed: current count=" 247 + mCountOfSatelliteNotificationDisplayed); 248 return this; 249 } 250 251 /** Increase the count of auto exit from P2P satellite messaging due to screen off. */ addCountOfAutoExitDueToScreenOff()252 public SessionMetricsStats addCountOfAutoExitDueToScreenOff() { 253 mCountOfAutoExitDueToScreenOff++; 254 logd("addCountOfAutoExitDueToScreenOff: current count=" + mCountOfAutoExitDueToScreenOff); 255 return this; 256 } 257 258 /** Increase the count of auto exit from P2P satellite messaging due to scan TN network. */ addCountOfAutoExitDueToTnNetwork()259 public SessionMetricsStats addCountOfAutoExitDueToTnNetwork() { 260 mCountOfAutoExitDueToTnNetwork++; 261 logd("addCountOfAutoExitDueToTnNetwork: current count=" + mCountOfAutoExitDueToTnNetwork); 262 return this; 263 } 264 265 /** Sets whether the session is enabled for emergency or not. */ setIsEmergency(boolean isEmergency)266 public SessionMetricsStats setIsEmergency(boolean isEmergency) { 267 mIsEmergency = isEmergency; 268 logd("setIsEmergency(" + mIsEmergency + ")"); 269 return this; 270 } 271 272 /** Capture the latest provisioned state for satellite service */ setIsNtnOnlyCarrier(boolean isNtnOnlyCarrier)273 public SessionMetricsStats setIsNtnOnlyCarrier(boolean isNtnOnlyCarrier) { 274 mIsNtnOnlyCarrier = isNtnOnlyCarrier; 275 logd("setIsNtnOnlyCarrier(" + mIsNtnOnlyCarrier + ")"); 276 return this; 277 } 278 279 /** Updates the max inactivity duration session metric. */ updateMaxInactivityDurationSec(int inactivityDurationSec)280 public SessionMetricsStats updateMaxInactivityDurationSec(int inactivityDurationSec) { 281 if (inactivityDurationSec > mMaxInactivityDurationSec) { 282 mMaxInactivityDurationSec = inactivityDurationSec; 283 } 284 logd("updateMaxInactivityDurationSec: latest inactivty duration (sec)=" 285 + inactivityDurationSec 286 + ", max inactivity duration=" 287 + mMaxInactivityDurationSec); 288 return this; 289 } 290 291 /** Report the session metrics atoms to PersistAtomsStorage in telephony. */ reportSessionMetrics()292 public void reportSessionMetrics() { 293 SatelliteStats.SatelliteSessionParams sessionParams = 294 new SatelliteStats.SatelliteSessionParams.Builder() 295 .setSatelliteServiceInitializationResult(mInitializationResult) 296 .setSatelliteTechnology(mRadioTechnology) 297 .setTerminationResult(mTerminationResult) 298 .setInitializationProcessingTime(mInitializationProcessingTimeMillis) 299 .setTerminationProcessingTime(mTerminationProcessingTimeMillis) 300 .setSessionDuration(mSessionDurationSec) 301 .setCountOfOutgoingDatagramSuccess(mCountOfSuccessfulOutgoingDatagram) 302 .setCountOfOutgoingDatagramFailed(mCountOfFailedOutgoingDatagram) 303 .setCountOfIncomingDatagramSuccess(mCountOfSuccessfulIncomingDatagram) 304 .setCountOfIncomingDatagramFailed(mCountOfIncomingDatagramFailed) 305 .setIsDemoMode(mIsDemoMode) 306 .setMaxNtnSignalStrengthLevel(mMaxNtnSignalStrengthLevel) 307 .setCarrierId(mCarrierId) 308 .setCountOfSatelliteNotificationDisplayed( 309 mCountOfSatelliteNotificationDisplayed) 310 .setCountOfAutoExitDueToScreenOff(mCountOfAutoExitDueToScreenOff) 311 .setCountOfAutoExitDueToTnNetwork(mCountOfAutoExitDueToTnNetwork) 312 .setIsEmergency(mIsEmergency) 313 .setIsNtnOnlyCarrier(mIsNtnOnlyCarrier) 314 .setMaxInactivityDurationSec(mMaxInactivityDurationSec) 315 .build(); 316 logd("reportSessionMetrics: " + sessionParams.toString()); 317 SatelliteStats.getInstance().onSatelliteSessionMetrics(sessionParams); 318 initializeSessionMetricsParam(); 319 } 320 321 /** Returns {@link SatelliteSessionStats} of the satellite service. */ requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result)322 public void requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result) { 323 Log.i(TAG, "requestSatelliteSessionStats called"); 324 Bundle bundle = new Bundle(); 325 SatelliteSessionStats sessionStats = new SatelliteSessionStats.Builder() 326 .setCountOfSuccessfulUserMessages(mShadowCountOfSuccessfulOutgoingDatagram) 327 .setCountOfUnsuccessfulUserMessages(mShadowCountOfFailedOutgoingDatagram) 328 .setCountOfTimedOutUserMessagesWaitingForConnection( 329 mShadowCountOfTimedOutUserMessagesWaitingForConnection) 330 .setCountOfTimedOutUserMessagesWaitingForAck( 331 mShadowCountOfTimedOutUserMessagesWaitingForAck) 332 .setCountOfUserMessagesInQueueToBeSent( 333 DatagramDispatcher.getInstance().getPendingUserMessagesCount()) 334 .build(); 335 bundle.putParcelable(SatelliteManager.KEY_SESSION_STATS, sessionStats); 336 337 // Reset countOfUserMessagesInQueueToBeSent for each datagramType to 0. 338 mDatagramStats.resetCountOfUserMessagesInQueueToBeSent(); 339 340 DatagramDispatcher.getInstance().updateSessionStatsWithPendingUserMsgCount(mDatagramStats); 341 bundle.putParcelable(KEY_SESSION_STATS_V2, mDatagramStats); 342 Log.i(TAG, "[END] DatagramStats = " + mDatagramStats); 343 result.send(SATELLITE_RESULT_SUCCESS, bundle); 344 } 345 346 /** Returns the processing time for satellite session initialization. */ getSessionInitializationProcessingTimeMillis()347 public long getSessionInitializationProcessingTimeMillis() { 348 return mInitializationProcessingTimeMillis; 349 } 350 351 /** Returns the processing time for satellite session termination. */ getSessionTerminationProcessingTimeMillis()352 public long getSessionTerminationProcessingTimeMillis() { 353 return mTerminationProcessingTimeMillis; 354 } 355 initializeSessionMetricsParam()356 private void initializeSessionMetricsParam() { 357 mInitializationResult = SATELLITE_RESULT_SUCCESS; 358 mRadioTechnology = SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN; 359 mTerminationResult = SATELLITE_RESULT_SUCCESS; 360 mInitializationProcessingTimeMillis = 0; 361 mTerminationProcessingTimeMillis = 0; 362 mSessionDurationSec = 0; 363 mCountOfSuccessfulOutgoingDatagram = 0; 364 mCountOfFailedOutgoingDatagram = 0; 365 mCountOfTimedOutUserMessagesWaitingForConnection = 0; 366 mCountOfTimedOutUserMessagesWaitingForAck = 0; 367 mCountOfSuccessfulIncomingDatagram = 0; 368 mCountOfIncomingDatagramFailed = 0; 369 mIsDemoMode = false; 370 mMaxNtnSignalStrengthLevel = NTN_SIGNAL_STRENGTH_NONE; 371 mCarrierId = UNKNOWN_CARRIER_ID; 372 mCountOfSatelliteNotificationDisplayed = 0; 373 mCountOfAutoExitDueToScreenOff = 0; 374 mCountOfAutoExitDueToTnNetwork = 0; 375 mIsEmergency = false; 376 mIsNtnOnlyCarrier = false; 377 mMaxInactivityDurationSec = 0; 378 } 379 resetSessionStatsShadowCounters()380 public void resetSessionStatsShadowCounters() { 381 logd("resetTheStatsCounters"); 382 mShadowCountOfSuccessfulOutgoingDatagram = 0; 383 mShadowCountOfFailedOutgoingDatagram = 0; 384 mShadowCountOfTimedOutUserMessagesWaitingForConnection = 0; 385 mShadowCountOfTimedOutUserMessagesWaitingForAck = 0; 386 mDatagramStats.clear(); 387 } 388 logd(@onNull String log)389 private static void logd(@NonNull String log) { 390 Log.d(TAG, log); 391 } 392 loge(@onNull String log)393 private static void loge(@NonNull String log) { 394 Log.e(TAG, log); 395 } 396 } 397