• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.satellite.metrics;
18 
19 import android.annotation.NonNull;
20 import android.os.SystemClock;
21 import android.telephony.SubscriptionManager;
22 import android.telephony.TelephonyManager;
23 import android.util.Log;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 import com.android.internal.telephony.Phone;
27 import com.android.internal.telephony.PhoneFactory;
28 import com.android.internal.telephony.metrics.SatelliteStats;
29 import com.android.internal.telephony.satellite.SatelliteConstants;
30 import com.android.internal.telephony.satellite.SatelliteServiceUtils;
31 import com.android.internal.telephony.subscription.SubscriptionManagerService;
32 
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 
39 public class CarrierRoamingSatelliteControllerStats {
40     private static final String TAG = CarrierRoamingSatelliteControllerStats.class.getSimpleName();
41     private static CarrierRoamingSatelliteControllerStats sInstance = null;
42     private static final int ADD_COUNT = 1;
43     private SatelliteStats mSatelliteStats;
44     /** Map key subId, value: list of session start time in milliseconds */
45     private Map<Integer, List<Long>> mSessionStartTimeMap = new HashMap<>();
46     /** Map key subId, list of session end time in milliseconds */
47     private Map<Integer, List<Long>> mSessionEndTimeMap = new HashMap<>();
48 
49     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
CarrierRoamingSatelliteControllerStats()50     public CarrierRoamingSatelliteControllerStats() {
51         mSatelliteStats = SatelliteStats.getInstance();
52         resetSessionGapLists();
53     }
54 
55     /**
56      * Returns the Singleton instance of CarrierRoamingSatelliteControllerStats class.
57      * If an instance of the Singleton class has not been created,
58      * it creates a new instance and returns it. Otherwise, it returns
59      * the existing instance.
60      * @return the Singleton instance of CarrierRoamingSatelliteControllerStats
61      */
getOrCreateInstance()62     public static CarrierRoamingSatelliteControllerStats getOrCreateInstance() {
63         if (sInstance == null) {
64             logd("Create new CarrierRoamingSatelliteControllerStats.");
65             sInstance = new CarrierRoamingSatelliteControllerStats();
66         }
67         return sInstance;
68     }
69 
70     /** Report config data source */
reportConfigDataSource(int subId, @SatelliteConstants.ConfigDataSource int configDataSource)71     public void reportConfigDataSource(int subId,
72             @SatelliteConstants.ConfigDataSource int configDataSource) {
73         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
74                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
75                         .setConfigDataSource(configDataSource)
76                         .setCarrierId(getCarrierIdFromSubscription(subId))
77                         .setIsMultiSim(isMultiSim())
78                         .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
79                         .build());
80     }
81 
82     /** Report count of entitlement status query request */
reportCountOfEntitlementStatusQueryRequest(int subId)83     public void reportCountOfEntitlementStatusQueryRequest(int subId) {
84         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
85                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
86                         .setCountOfEntitlementStatusQueryRequest(ADD_COUNT)
87                         .setCarrierId(getCarrierIdFromSubscription(subId))
88                         .setIsMultiSim(isMultiSim())
89                         .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
90                         .build());
91     }
92 
93     /** Report count of satellite config update request */
reportCountOfSatelliteConfigUpdateRequest()94     public void reportCountOfSatelliteConfigUpdateRequest() {
95         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
96                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
97                         .setCountOfSatelliteConfigUpdateRequest(ADD_COUNT)
98                         .setIsMultiSim(isMultiSim())
99                         .build());
100     }
101 
102     /** Report count of satellite notification displayed */
reportCountOfSatelliteNotificationDisplayed(int subId)103     public void reportCountOfSatelliteNotificationDisplayed(int subId) {
104         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
105                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
106                         .setCountOfSatelliteNotificationDisplayed(ADD_COUNT)
107                         .setCarrierId(getCarrierIdFromSubscription(subId))
108                         .setIsMultiSim(isMultiSim())
109                         .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
110                         .build());
111     }
112 
113     /** Capture the NB-IoT NTN carrier ID */
reportCarrierId(int carrierId)114     public void reportCarrierId(int carrierId) {
115         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
116                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
117                         .setCarrierId(carrierId)
118                         .setIsMultiSim(isMultiSim())
119                         .build());
120     }
121 
122     /** Capture whether the device is satellite entitled or not */
reportIsDeviceEntitled(int subId, boolean isDeviceEntitled)123     public void reportIsDeviceEntitled(int subId, boolean isDeviceEntitled) {
124         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
125                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
126                         .setIsDeviceEntitled(isDeviceEntitled)
127                         .setCarrierId(getCarrierIdFromSubscription(subId))
128                         .setIsMultiSim(isMultiSim())
129                         .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
130                         .build());
131     }
132 
133     /** Log carrier roaming satellite session start */
onSessionStart(int subId)134     public void onSessionStart(int subId) {
135         List<Long> sessionStartTimeListForSubscription = mSessionStartTimeMap.getOrDefault(subId,
136                 new ArrayList<>());
137         sessionStartTimeListForSubscription.add(getElapsedRealtime());
138         mSessionStartTimeMap.put(subId, sessionStartTimeListForSubscription);
139 
140         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
141                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
142                         .setCarrierId(getCarrierIdFromSubscription(subId))
143                         .increaseCountOfSatelliteSessions()
144                         .build());
145     }
146 
147     /** Log carrier roaming satellite session end */
onSessionEnd(int subId)148     public void onSessionEnd(int subId) {
149         List<Long> sessionEndTimeListForSubscription = mSessionEndTimeMap.getOrDefault(subId,
150                 new ArrayList<>());
151         sessionEndTimeListForSubscription.add(getElapsedRealtime());
152         mSessionEndTimeMap.put(subId, sessionEndTimeListForSubscription);
153 
154         int numberOfSatelliteSessions = getNumberOfSatelliteSessions(subId);
155         List<Integer> sessionGapList = getSatelliteSessionGapList(subId, numberOfSatelliteSessions);
156         int satelliteSessionGapMinSec = 0;
157         int satelliteSessionGapMaxSec = 0;
158         if (!sessionGapList.isEmpty()) {
159             satelliteSessionGapMinSec = Collections.min(sessionGapList);
160             satelliteSessionGapMaxSec = Collections.max(sessionGapList);
161         }
162 
163         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
164                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
165                         .setSatelliteSessionGapMinSec(satelliteSessionGapMinSec)
166                         .setSatelliteSessionGapAvgSec(getAvg(sessionGapList))
167                         .setSatelliteSessionGapMaxSec(satelliteSessionGapMaxSec)
168                         .setCarrierId(getCarrierIdFromSubscription(subId))
169                         .setIsMultiSim(isMultiSim())
170                         .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
171                         .build());
172     }
173 
174     /** Atom is pulled once per day. Reset session gap lists after the atom is pulled. */
resetSessionGapLists()175     public void resetSessionGapLists() {
176         mSessionStartTimeMap = new HashMap<>();
177         mSessionEndTimeMap = new HashMap<>();
178     }
179 
getNumberOfSatelliteSessions(int subId)180     private int getNumberOfSatelliteSessions(int subId) {
181         return Math.min(mSessionStartTimeMap.getOrDefault(subId, new ArrayList<>()).size(),
182                 mSessionEndTimeMap.getOrDefault(subId, new ArrayList<>()).size());
183     }
184 
getSatelliteSessionGapList(int subId, int numberOfSatelliteSessions)185     private List<Integer> getSatelliteSessionGapList(int subId, int numberOfSatelliteSessions) {
186         if (numberOfSatelliteSessions == 0) {
187             return new ArrayList<>();
188         }
189 
190         List<Long> sessionStartTimeList = mSessionStartTimeMap.getOrDefault(subId,
191                 new ArrayList<>());
192         List<Long> sessionEndTimeList = mSessionEndTimeMap.getOrDefault(subId, new ArrayList<>());
193         List<Integer> sessionGapList = new ArrayList<>();
194         for (int i = 1; i < numberOfSatelliteSessions; i++) {
195             long prevSessionEndTime = sessionEndTimeList.get(i - 1);
196             long currentSessionStartTime = sessionStartTimeList.get(i);
197             if (currentSessionStartTime > prevSessionEndTime && prevSessionEndTime > 0) {
198                 sessionGapList.add((int) (
199                         (currentSessionStartTime - prevSessionEndTime) / 1000));
200             }
201         }
202         return sessionGapList;
203     }
204 
getAvg(@onNull List<Integer> list)205     private int getAvg(@NonNull List<Integer> list) {
206         if (list.isEmpty()) {
207             return 0;
208         }
209 
210         int total = 0;
211         for (int num : list) {
212             total += num;
213         }
214 
215         return total / list.size();
216     }
217 
218     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getElapsedRealtime()219     protected long getElapsedRealtime() {
220         return SystemClock.elapsedRealtime();
221     }
222 
223     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
isMultiSim()224     public boolean isMultiSim() {
225         return SubscriptionManagerService.getInstance().getActiveSubIdList(true).length > 1;
226     }
227 
228     /** Returns the carrier ID of the given subscription id. */
229     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
getCarrierIdFromSubscription(int subId)230     protected int getCarrierIdFromSubscription(int subId) {
231         int phoneId = SubscriptionManager.getPhoneId(subId);
232         Phone phone = PhoneFactory.getPhone(phoneId);
233         return phone != null ? phone.getCarrierId() : TelephonyManager.UNKNOWN_CARRIER_ID;
234     }
235 
logd(@onNull String log)236     private static void logd(@NonNull String log) {
237         Log.d(TAG, log);
238     }
239 }
240