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