18c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt/*
28c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * Copyright (C) 2016 The Android Open Source Project
38c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt *
48c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
58c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * you may not use this file except in compliance with the License.
68c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * You may obtain a copy of the License at
78c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt *
88c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
98c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt *
108c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * Unless required by applicable law or agreed to in writing, software
118c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
128c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * See the License for the specific language governing permissions and
148c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * limitations under the License.
158c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt */
168c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltpackage com.android.internal.telephony;
178c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
188c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.content.BroadcastReceiver;
198c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.content.Context;
208c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.content.Intent;
218c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.content.IntentFilter;
228c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.os.PersistableBundle;
238c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.os.UserHandle;
248c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.telephony.CarrierConfigManager;
252cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwaltimport android.telephony.ServiceState;
268c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.telephony.Rlog;
278c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.util.SparseArray;
288c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport android.util.SparseIntArray;
298c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
308c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltimport java.util.ArrayList;
318c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
328c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt/**
338c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * This class loads configuration from CarrierConfig and uses it to determine
348c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * what RATs are within a ratcheting family.  For example all the HSPA/HSDPA/HSUPA RATs.
358c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * Then, until reset the class will only ratchet upwards within the family (order
368c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * determined by the CarrierConfig data).  The ServiceStateTracker will reset this
378c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt * on cell-change.
388c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt */
398c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwaltpublic class RatRatcheter {
408c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    private final static String LOG_TAG = "RilRatcheter";
418c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
428c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    /**
438c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt     * This is a map of RAT types -> RAT families for rapid lookup.
448c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt     * The RAT families are defined by RAT type -> RAT Rank SparseIntArrays, so
458c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt     * we can compare the priorities of two RAT types by comparing the values
468c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt     * stored in the SparseIntArrays, higher values are higher priority.
478c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt     */
488c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    private final SparseArray<SparseIntArray> mRatFamilyMap = new SparseArray<>();
498c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
508c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    private final Phone mPhone;
518c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
528c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    /** Constructor */
538c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    public RatRatcheter(Phone phone) {
548c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        mPhone = phone;
558c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
568c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        IntentFilter intentFilter = new IntentFilter();
578c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
588c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        phone.getContext().registerReceiverAsUser(mConfigChangedReceiver, UserHandle.ALL,
598c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                intentFilter, null, null);
608c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        resetRatFamilyMap();
618c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    }
628c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
638c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    public int ratchetRat(int oldRat, int newRat) {
648c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        synchronized (mRatFamilyMap) {
658c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            final SparseIntArray oldFamily = mRatFamilyMap.get(oldRat);
668c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            if (oldFamily == null) return newRat;
678c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
688c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            final SparseIntArray newFamily = mRatFamilyMap.get(newRat);
698c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            if (newFamily != oldFamily) return newRat;
708c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
718c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            // now go with the higher of the two
728c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            final int oldRatRank = newFamily.get(oldRat, -1);
738c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            final int newRatRank = newFamily.get(newRat, -1);
748c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            return (oldRatRank > newRatRank ? oldRat : newRat);
758c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        }
768c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    }
778c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
782cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt    public void ratchetRat(ServiceState oldSS, ServiceState newSS) {
792cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt        int newVoiceRat = ratchetRat(oldSS.getRilVoiceRadioTechnology(),
802cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt                newSS.getRilVoiceRadioTechnology());
812cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt        int newDataRat = ratchetRat(oldSS.getRilDataRadioTechnology(),
822cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt                newSS.getRilDataRadioTechnology());
832cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt        boolean newUsingCA = oldSS.isUsingCarrierAggregation() ||
842cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt                newSS.isUsingCarrierAggregation();
852cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt
862cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt        newSS.setRilVoiceRadioTechnology(newVoiceRat);
872cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt        newSS.setRilDataRadioTechnology(newDataRat);
882cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt        newSS.setIsUsingCarrierAggregation(newUsingCA);
892cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt    }
902cd7606f4d72cb7340c164aebb1835cd87f4996cRobert Greenwalt
918c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    private BroadcastReceiver mConfigChangedReceiver = new BroadcastReceiver() {
928c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        @Override
938c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        public void onReceive(Context context, Intent intent) {
948c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            final String action = intent.getAction();
958c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)) {
968c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                resetRatFamilyMap();
978c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            }
988c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        }
998c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    };
1008c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
1018c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    private void resetRatFamilyMap() {
1028c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        synchronized(mRatFamilyMap) {
1038c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            mRatFamilyMap.clear();
1048c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
1058c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            final CarrierConfigManager configManager = (CarrierConfigManager)
1068c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
1078c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            if (configManager == null) return;
1088c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            PersistableBundle b = configManager.getConfig();
1098c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            if (b == null) return;
1108c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt
1118c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            // Reads an array of strings, eg:
1128c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            // ["GPRS, EDGE", "EVDO, EVDO_A, EVDO_B", "HSPA, HSDPA, HSUPA, HSPAP"]
1138c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            // Each string defines a family and the order of rats within the string express
1148c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            // the priority of the RAT within the family (ie, we'd move up to later-listed RATs, but
1158c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            // not down).
1168c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            String[] ratFamilies = b.getStringArray(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES);
1178c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            if (ratFamilies == null) return;
1188c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            for (String ratFamily : ratFamilies) {
1198c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                String[] rats = ratFamily.split(",");
1208c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                if (rats.length < 2) continue;
1218c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                SparseIntArray currentFamily = new SparseIntArray(rats.length);
1228c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                int pos = 0;
1238c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                for (String ratString : rats) {
1248c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    int ratInt;
1258c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    try {
1268c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                        ratInt = Integer.parseInt(ratString.trim());
1278c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    } catch (NumberFormatException e) {
1288c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                        Rlog.e(LOG_TAG, "NumberFormatException on " + ratString);
1298c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                        break;
1308c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    }
1318c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    if (mRatFamilyMap.get(ratInt) != null) {
1328c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                        Rlog.e(LOG_TAG, "RAT listed twice: " + ratString);
1338c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                        break;
1348c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    }
1358c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    currentFamily.put(ratInt, pos++);
1368c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                    mRatFamilyMap.put(ratInt, currentFamily);
1378c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt                }
1388c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt            }
1398c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt        }
1408c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt    }
1418c751b4ec57a6f2a7702d9ee003b0ec721c2ebacRobert Greenwalt}
142