1 /* 2 * Copyright (C) 2020 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.net; 18 19 import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; 20 import static android.net.NetworkTemplate.getCollapsedRatType; 21 22 import android.annotation.NonNull; 23 import android.content.Context; 24 import android.telephony.Annotation; 25 import android.telephony.NetworkRegistrationInfo; 26 import android.telephony.PhoneStateListener; 27 import android.telephony.ServiceState; 28 import android.telephony.SubscriptionManager; 29 import android.telephony.TelephonyManager; 30 import android.text.TextUtils; 31 import android.util.Log; 32 33 import com.android.internal.annotations.VisibleForTesting; 34 import com.android.internal.util.CollectionUtils; 35 36 import java.util.ArrayList; 37 import java.util.List; 38 import java.util.concurrent.CopyOnWriteArrayList; 39 import java.util.concurrent.Executor; 40 41 /** 42 * Helper class that watches for events that are triggered per subscription. 43 */ 44 public class NetworkStatsSubscriptionsMonitor extends 45 SubscriptionManager.OnSubscriptionsChangedListener { 46 47 /** 48 * Interface that this monitor uses to delegate event handling to NetworkStatsService. 49 */ 50 public interface Delegate { 51 /** 52 * Notify that the collapsed RAT type has been changed for any subscription. The method 53 * will also be triggered for any existing sub when start and stop monitoring. 54 * 55 * @param subscriberId IMSI of the subscription. 56 * @param collapsedRatType collapsed RAT type. 57 * @see android.net.NetworkTemplate#getCollapsedRatType(int). 58 */ onCollapsedRatTypeChanged(@onNull String subscriberId, @Annotation.NetworkType int collapsedRatType)59 void onCollapsedRatTypeChanged(@NonNull String subscriberId, 60 @Annotation.NetworkType int collapsedRatType); 61 } 62 private final Delegate mDelegate; 63 64 /** 65 * Receivers that watches for {@link ServiceState} changes for each subscription, to 66 * monitor the transitioning between Radio Access Technology(RAT) types for each sub. 67 */ 68 @NonNull 69 private final CopyOnWriteArrayList<RatTypeListener> mRatListeners = 70 new CopyOnWriteArrayList<>(); 71 72 @NonNull 73 private final SubscriptionManager mSubscriptionManager; 74 @NonNull 75 private final TelephonyManager mTeleManager; 76 77 @NonNull 78 private final Executor mExecutor; 79 NetworkStatsSubscriptionsMonitor(@onNull Context context, @NonNull Executor executor, @NonNull Delegate delegate)80 NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor, 81 @NonNull Delegate delegate) { 82 super(); 83 mSubscriptionManager = (SubscriptionManager) context.getSystemService( 84 Context.TELEPHONY_SUBSCRIPTION_SERVICE); 85 mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 86 mExecutor = executor; 87 mDelegate = delegate; 88 } 89 90 @Override onSubscriptionsChanged()91 public void onSubscriptionsChanged() { 92 // Collect active subId list, hidden subId such as opportunistic subscriptions are 93 // also needed to track CBRS. 94 final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager); 95 96 for (final int subId : newSubs) { 97 final RatTypeListener match = CollectionUtils.find(mRatListeners, 98 it -> it.mSubId == subId); 99 if (match != null) continue; 100 101 // Create listener for every newly added sub. Also store subscriberId into it to 102 // prevent binder call to telephony when querying RAT. 103 final String subscriberId = mTeleManager.getSubscriberId(subId); 104 if (TextUtils.isEmpty(subscriberId)) { 105 Log.wtf(NetworkStatsService.TAG, 106 "Empty subscriberId for newly added sub: " + subId); 107 } 108 final RatTypeListener listener = 109 new RatTypeListener(mExecutor, this, subId, subscriberId); 110 mRatListeners.add(listener); 111 112 // Register listener to the telephony manager that associated with specific sub. 113 mTeleManager.createForSubscriptionId(subId) 114 .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); 115 } 116 117 for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { 118 // If the new list contains the subId of the listener, keeps it. 119 final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId); 120 if (match != null) continue; 121 122 handleRemoveRatTypeListener(listener); 123 } 124 } 125 126 @NonNull getActiveSubIdList(@onNull SubscriptionManager subscriptionManager)127 private List<Integer> getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) { 128 final ArrayList<Integer> ret = new ArrayList<>(); 129 final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList(); 130 for (int id : ids) ret.add(id); 131 return ret; 132 } 133 134 /** 135 * Get a collapsed RatType for the given subscriberId. 136 * 137 * @param subscriberId the target subscriberId 138 * @return collapsed RatType for the given subscriberId 139 */ getRatTypeForSubscriberId(@onNull String subscriberId)140 public int getRatTypeForSubscriberId(@NonNull String subscriberId) { 141 final RatTypeListener match = CollectionUtils.find(mRatListeners, 142 it -> TextUtils.equals(subscriberId, it.mSubscriberId)); 143 return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN; 144 } 145 146 /** 147 * Start monitoring events that triggered per subscription. 148 */ start()149 public void start() { 150 mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this); 151 } 152 153 /** 154 * Unregister subscription changes and all listeners for each subscription. 155 */ stop()156 public void stop() { 157 mSubscriptionManager.removeOnSubscriptionsChangedListener(this); 158 159 for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { 160 handleRemoveRatTypeListener(listener); 161 } 162 } 163 handleRemoveRatTypeListener(@onNull RatTypeListener listener)164 private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { 165 mTeleManager.createForSubscriptionId(listener.mSubId) 166 .listen(listener, PhoneStateListener.LISTEN_NONE); 167 mRatListeners.remove(listener); 168 169 // Removal of subscriptions doesn't generate RAT changed event, fire it for every 170 // RatTypeListener. 171 mDelegate.onCollapsedRatTypeChanged( 172 listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN); 173 } 174 175 static class RatTypeListener extends PhoneStateListener { 176 // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}. 177 @NonNull 178 private final int mSubId; 179 180 // IMSI to identifying the corresponding network from {@link NetworkState}. 181 // See {@link TelephonyManager#getSubscriberId}. 182 @NonNull 183 private final String mSubscriberId; 184 185 private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 186 @NonNull 187 private final NetworkStatsSubscriptionsMonitor mMonitor; 188 RatTypeListener(@onNull Executor executor, @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId, @NonNull String subscriberId)189 RatTypeListener(@NonNull Executor executor, 190 @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId, 191 @NonNull String subscriberId) { 192 super(executor); 193 mSubId = subId; 194 mSubscriberId = subscriberId; 195 mMonitor = monitor; 196 } 197 198 @Override onServiceStateChanged(@onNull ServiceState ss)199 public void onServiceStateChanged(@NonNull ServiceState ss) { 200 // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony 201 // would report RAT = 5G_NR. 202 // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and 203 // network allocates a secondary 5G cell so telephony reports RAT = LTE along with 204 // NR state as connected. In such case, attributes the data usage to NR. 205 // See b/160727498. 206 final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE 207 || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) 208 && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; 209 210 final int networkType = 211 (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType()); 212 final int collapsedRatType = getCollapsedRatType(networkType); 213 if (collapsedRatType == mLastCollapsedRatType) return; 214 215 if (NetworkStatsService.LOGD) { 216 Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): " 217 + mLastCollapsedRatType + " -> " + collapsedRatType); 218 } 219 mLastCollapsedRatType = collapsedRatType; 220 mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType); 221 } 222 223 @VisibleForTesting getSubId()224 public int getSubId() { 225 return mSubId; 226 } 227 } 228 } 229