1 /* 2 * Copyright (C) 2016 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 package com.android.internal.telephony; 17 18 import android.content.BroadcastReceiver; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.IntentFilter; 22 import android.os.PersistableBundle; 23 import android.os.UserHandle; 24 import android.telephony.CarrierConfigManager; 25 import android.telephony.ServiceState; 26 import android.telephony.Rlog; 27 import android.util.SparseArray; 28 import android.util.SparseIntArray; 29 30 import java.util.ArrayList; 31 32 /** 33 * This class loads configuration from CarrierConfig and uses it to determine 34 * what RATs are within a ratcheting family. For example all the HSPA/HSDPA/HSUPA RATs. 35 * Then, until reset the class will only ratchet upwards within the family (order 36 * determined by the CarrierConfig data). The ServiceStateTracker will reset this 37 * on cell-change. 38 */ 39 public class RatRatcheter { 40 private final static String LOG_TAG = "RilRatcheter"; 41 42 /** 43 * This is a map of RAT types -> RAT families for rapid lookup. 44 * The RAT families are defined by RAT type -> RAT Rank SparseIntArrays, so 45 * we can compare the priorities of two RAT types by comparing the values 46 * stored in the SparseIntArrays, higher values are higher priority. 47 */ 48 private final SparseArray<SparseIntArray> mRatFamilyMap = new SparseArray<>(); 49 50 private final Phone mPhone; 51 52 /** Constructor */ 53 public RatRatcheter(Phone phone) { 54 mPhone = phone; 55 56 IntentFilter intentFilter = new IntentFilter(); 57 intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 58 phone.getContext().registerReceiverAsUser(mConfigChangedReceiver, UserHandle.ALL, 59 intentFilter, null, null); 60 resetRatFamilyMap(); 61 } 62 63 public int ratchetRat(int oldRat, int newRat) { 64 synchronized (mRatFamilyMap) { 65 final SparseIntArray oldFamily = mRatFamilyMap.get(oldRat); 66 if (oldFamily == null) return newRat; 67 68 final SparseIntArray newFamily = mRatFamilyMap.get(newRat); 69 if (newFamily != oldFamily) return newRat; 70 71 // now go with the higher of the two 72 final int oldRatRank = newFamily.get(oldRat, -1); 73 final int newRatRank = newFamily.get(newRat, -1); 74 return (oldRatRank > newRatRank ? oldRat : newRat); 75 } 76 } 77 78 public void ratchetRat(ServiceState oldSS, ServiceState newSS) { 79 int newVoiceRat = ratchetRat(oldSS.getRilVoiceRadioTechnology(), 80 newSS.getRilVoiceRadioTechnology()); 81 int newDataRat = ratchetRat(oldSS.getRilDataRadioTechnology(), 82 newSS.getRilDataRadioTechnology()); 83 boolean newUsingCA = oldSS.isUsingCarrierAggregation() || 84 newSS.isUsingCarrierAggregation(); 85 86 newSS.setRilVoiceRadioTechnology(newVoiceRat); 87 newSS.setRilDataRadioTechnology(newDataRat); 88 newSS.setIsUsingCarrierAggregation(newUsingCA); 89 } 90 91 private BroadcastReceiver mConfigChangedReceiver = new BroadcastReceiver() { 92 @Override 93 public void onReceive(Context context, Intent intent) { 94 final String action = intent.getAction(); 95 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)) { 96 resetRatFamilyMap(); 97 } 98 } 99 }; 100 101 private void resetRatFamilyMap() { 102 synchronized(mRatFamilyMap) { 103 mRatFamilyMap.clear(); 104 105 final CarrierConfigManager configManager = (CarrierConfigManager) 106 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 107 if (configManager == null) return; 108 PersistableBundle b = configManager.getConfig(); 109 if (b == null) return; 110 111 // Reads an array of strings, eg: 112 // ["GPRS, EDGE", "EVDO, EVDO_A, EVDO_B", "HSPA, HSDPA, HSUPA, HSPAP"] 113 // Each string defines a family and the order of rats within the string express 114 // the priority of the RAT within the family (ie, we'd move up to later-listed RATs, but 115 // not down). 116 String[] ratFamilies = b.getStringArray(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES); 117 if (ratFamilies == null) return; 118 for (String ratFamily : ratFamilies) { 119 String[] rats = ratFamily.split(","); 120 if (rats.length < 2) continue; 121 SparseIntArray currentFamily = new SparseIntArray(rats.length); 122 int pos = 0; 123 for (String ratString : rats) { 124 int ratInt; 125 try { 126 ratInt = Integer.parseInt(ratString.trim()); 127 } catch (NumberFormatException e) { 128 Rlog.e(LOG_TAG, "NumberFormatException on " + ratString); 129 break; 130 } 131 if (mRatFamilyMap.get(ratInt) != null) { 132 Rlog.e(LOG_TAG, "RAT listed twice: " + ratString); 133 break; 134 } 135 currentFamily.put(ratInt, pos++); 136 mRatFamilyMap.put(ratInt, currentFamily); 137 } 138 } 139 } 140 } 141 } 142