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