1 /* 2 * Copyright (C) 2024 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.metrics; 18 19 import android.annotation.ElapsedRealtimeLong; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.os.SystemClock; 23 import android.telephony.Annotation.ApnType; 24 import android.telephony.Annotation.NetworkType; 25 import android.telephony.PreciseDataConnectionState; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 import com.android.internal.telephony.Phone; 29 import com.android.internal.telephony.PhoneFactory; 30 import com.android.internal.telephony.TelephonyStatsLog; 31 import com.android.internal.telephony.nano.PersistAtomsProto.DataNetworkValidation; 32 33 /** 34 * DataNetworkValidationStats logs the atoms for response after a validation request from the 35 * DataNetwork in framework. 36 */ 37 public class DataNetworkValidationStats { 38 39 private static final String TAG = DataNetworkValidationStats.class.getSimpleName(); 40 41 @NonNull 42 private final Phone mPhone; 43 44 @NonNull 45 private final PersistAtomsStorage mAtomsStorage = 46 PhoneFactory.getMetricsCollector().getAtomsStorage(); 47 48 @Nullable 49 private DataNetworkValidation mDataNetworkValidation; 50 51 @ElapsedRealtimeLong 52 private long mRequestedTimeInMillis; 53 54 /** constructor */ DataNetworkValidationStats(@onNull Phone phone)55 public DataNetworkValidationStats(@NonNull Phone phone) { 56 mPhone = phone; 57 } 58 59 60 /** 61 * Create a new ongoing atom when NetworkValidation requested. 62 * 63 * Create a data network validation proto for a new atom record and write the start time to 64 * calculate the elapsed time required. 65 * 66 * @param apnTypeBitMask APN type bitmask of DataNetwork. 67 */ onRequestNetworkValidation(@pnType int apnTypeBitMask)68 public void onRequestNetworkValidation(@ApnType int apnTypeBitMask) { 69 if (mDataNetworkValidation == null) { 70 mDataNetworkValidation = getDefaultProto(apnTypeBitMask); 71 mRequestedTimeInMillis = getTimeMillis(); 72 } 73 } 74 75 /** Mark the Handover Attempt field as true if validation was requested */ onHandoverAttempted()76 public void onHandoverAttempted() { 77 if (mDataNetworkValidation != null) { 78 mDataNetworkValidation.handoverAttempted = true; 79 } 80 } 81 82 /** 83 * Called when data network is disconnected. 84 * 85 * Since network validation is based on the data network, validation must also end when the data 86 * network is disconnected. At this time, validation has not been completed, save an atom as 87 * unspecified. and clear. 88 * 89 * @param networkType Current Network Type of the Data Network. 90 */ onDataNetworkDisconnected(@etworkType int networkType)91 public void onDataNetworkDisconnected(@NetworkType int networkType) { 92 // Nothing to do, if never requested validation 93 if (mDataNetworkValidation == null) { 94 return; 95 } 96 97 // Set data for and atom. 98 calcElapsedTime(); 99 mDataNetworkValidation.networkType = networkType; 100 mDataNetworkValidation.signalStrength = mPhone.getSignalStrength().getLevel(); 101 mDataNetworkValidation.validationResult = TelephonyStatsLog 102 .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_UNSPECIFIED; 103 104 // Store. 105 mAtomsStorage.addDataNetworkValidation(mDataNetworkValidation); 106 107 // clear all values. 108 clear(); 109 } 110 111 /** 112 * Store an atom by updated state. 113 * 114 * Called when the validation status is updated, and saves the atom when a failure or success 115 * result is received. 116 * 117 * @param status Data Network Validation Status. 118 * @param networkType Current Network Type of the Data Network. 119 */ onUpdateNetworkValidationState( @reciseDataConnectionState.NetworkValidationStatus int status, @NetworkType int networkType)120 public void onUpdateNetworkValidationState( 121 @PreciseDataConnectionState.NetworkValidationStatus int status, 122 @NetworkType int networkType) { 123 // Nothing to do, if never requested validation 124 if (mDataNetworkValidation == null) { 125 return; 126 } 127 128 switch (status) { 129 // Immediately after requesting validation, these messages may occur. In this case, 130 // ignore it and wait for the next update. 131 case PreciseDataConnectionState.NETWORK_VALIDATION_NOT_REQUESTED: // fall-through 132 case PreciseDataConnectionState.NETWORK_VALIDATION_IN_PROGRESS: 133 return; 134 // If status is unsupported, NetworkValidation should not be requested initially. logs 135 // this for abnormal tracking. 136 case PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED: 137 mDataNetworkValidation.validationResult = TelephonyStatsLog 138 .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_NOT_SUPPORTED; 139 break; 140 // Success or failure corresponds to the result, store an atom. 141 case PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS: 142 case PreciseDataConnectionState.NETWORK_VALIDATION_FAILURE: 143 mDataNetworkValidation.validationResult = status; 144 break; 145 } 146 147 // Set data for and atom. 148 calcElapsedTime(); 149 mDataNetworkValidation.networkType = networkType; 150 mDataNetworkValidation.signalStrength = mPhone.getSignalStrength().getLevel(); 151 152 // Store. 153 mAtomsStorage.addDataNetworkValidation(mDataNetworkValidation); 154 155 // clear all values. 156 clear(); 157 } 158 159 /** 160 * Calculate the current time required based on when network validation is requested. 161 */ calcElapsedTime()162 private void calcElapsedTime() { 163 if (mDataNetworkValidation != null && mRequestedTimeInMillis != 0) { 164 mDataNetworkValidation.elapsedTimeInMillis = getTimeMillis() - mRequestedTimeInMillis; 165 } 166 } 167 168 /** 169 * Returns current time in millis from boot. 170 */ 171 @VisibleForTesting 172 @ElapsedRealtimeLong getTimeMillis()173 protected long getTimeMillis() { 174 return SystemClock.elapsedRealtime(); 175 } 176 177 /** 178 * Clear all values. 179 */ clear()180 private void clear() { 181 mDataNetworkValidation = null; 182 mRequestedTimeInMillis = 0; 183 } 184 185 186 /** Creates a DataNetworkValidation proto with default values. */ 187 @NonNull getDefaultProto(@pnType int apnTypeBitmask)188 private DataNetworkValidation getDefaultProto(@ApnType int apnTypeBitmask) { 189 DataNetworkValidation proto = new DataNetworkValidation(); 190 proto.networkType = 191 TelephonyStatsLog.DATA_NETWORK_VALIDATION__NETWORK_TYPE__NETWORK_TYPE_UNKNOWN; 192 proto.apnTypeBitmask = apnTypeBitmask; 193 proto.signalStrength = 194 TelephonyStatsLog 195 .DATA_NETWORK_VALIDATION__SIGNAL_STRENGTH__SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 196 proto.validationResult = 197 TelephonyStatsLog 198 .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_UNSPECIFIED; 199 proto.elapsedTimeInMillis = 0; 200 proto.handoverAttempted = false; 201 proto.networkValidationCount = 1; 202 return proto; 203 } 204 } 205 206