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