Home | History | Annotate | Download | only in telephony
      1 /*
      2 * Copyright (C) 2015 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.internal.telephony;
     18 
     19 import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
     20 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     21 
     22 import android.content.BroadcastReceiver;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.content.IntentFilter;
     26 import android.os.Handler;
     27 import android.os.Registrant;
     28 import android.os.RegistrantList;
     29 import android.os.RemoteException;
     30 import android.os.ServiceManager;
     31 import android.telephony.Rlog;
     32 import android.telephony.SubscriptionManager;
     33 import android.util.LocalLog;
     34 
     35 import com.android.internal.annotations.VisibleForTesting;
     36 import com.android.internal.telephony.ISub;
     37 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
     38 import com.android.internal.telephony.ITelephonyRegistry;
     39 import com.android.internal.telephony.PhoneConstants;
     40 
     41 import java.io.FileDescriptor;
     42 import java.io.PrintWriter;
     43 import java.lang.IllegalArgumentException;
     44 
     45 /**
     46  * Utility singleton to monitor subscription changes and help people act on them.
     47  * Uses Registrant model to post messages to handlers.
     48  *
     49  */
     50 public class SubscriptionMonitor {
     51 
     52     private final RegistrantList mSubscriptionsChangedRegistrants[];
     53     private final RegistrantList mDefaultDataSubChangedRegistrants[];
     54 
     55     private final SubscriptionController mSubscriptionController;
     56     private final Context mContext;
     57 
     58     private final int mPhoneSubId[];
     59     private int mDefaultDataSubId;
     60     private int mDefaultDataPhoneId;
     61 
     62     private final Object mLock = new Object();
     63 
     64     private final static boolean VDBG = true;
     65     private final static String LOG_TAG = "SubscriptionMonitor";
     66 
     67     private final static int MAX_LOGLINES = 100;
     68     private final LocalLog mLocalLog = new LocalLog(MAX_LOGLINES);
     69 
     70     public SubscriptionMonitor(ITelephonyRegistry tr, Context context,
     71             SubscriptionController subscriptionController, int numPhones) {
     72         try {
     73             tr.addOnSubscriptionsChangedListener(context.getOpPackageName(),
     74                     mSubscriptionsChangedListener);
     75         } catch (RemoteException e) {
     76         }
     77 
     78         mSubscriptionController = subscriptionController;
     79         mContext = context;
     80 
     81         mSubscriptionsChangedRegistrants = new RegistrantList[numPhones];
     82         mDefaultDataSubChangedRegistrants = new RegistrantList[numPhones];
     83         mPhoneSubId = new int[numPhones];
     84 
     85         mDefaultDataSubId = mSubscriptionController.getDefaultDataSubId();
     86         mDefaultDataPhoneId = mSubscriptionController.getPhoneId(mDefaultDataSubId);
     87 
     88         for (int phoneId = 0; phoneId < numPhones; phoneId++) {
     89             mSubscriptionsChangedRegistrants[phoneId] = new RegistrantList();
     90             mDefaultDataSubChangedRegistrants[phoneId] = new RegistrantList();
     91             mPhoneSubId[phoneId] = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
     92         }
     93 
     94         mContext.registerReceiver(mDefaultDataSubscriptionChangedReceiver,
     95                 new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
     96     }
     97 
     98     @VisibleForTesting
     99     public SubscriptionMonitor() {
    100         mSubscriptionsChangedRegistrants = null;
    101         mDefaultDataSubChangedRegistrants = null;
    102         mSubscriptionController = null;
    103         mContext = null;
    104         mPhoneSubId = null;
    105     }
    106 
    107     private final IOnSubscriptionsChangedListener mSubscriptionsChangedListener =
    108             new IOnSubscriptionsChangedListener.Stub() {
    109         @Override
    110         public void onSubscriptionsChanged() {
    111             synchronized (mLock) {
    112                 int newDefaultDataPhoneId = INVALID_PHONE_INDEX;
    113                 for (int phoneId = 0; phoneId < mPhoneSubId.length; phoneId++) {
    114                     final int newSubId = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
    115                     final int oldSubId = mPhoneSubId[phoneId];
    116                     if (oldSubId != newSubId) {
    117                         log("Phone[" + phoneId + "] subId changed " + oldSubId + "->" +
    118                                 newSubId + ", " +
    119                                 mSubscriptionsChangedRegistrants[phoneId].size() + " registrants");
    120                         mPhoneSubId[phoneId] = newSubId;
    121                         mSubscriptionsChangedRegistrants[phoneId].notifyRegistrants();
    122 
    123                         // if the default isn't set, just move along..
    124                         if (mDefaultDataSubId == INVALID_SUBSCRIPTION_ID) continue;
    125 
    126                         // check if this affects default data
    127                         if (newSubId == mDefaultDataSubId || oldSubId == mDefaultDataSubId) {
    128                             log("mDefaultDataSubId = " + mDefaultDataSubId + ", " +
    129                                     mDefaultDataSubChangedRegistrants[phoneId].size() +
    130                                     " registrants");
    131                             mDefaultDataSubChangedRegistrants[phoneId].notifyRegistrants();
    132                         }
    133                     }
    134                     if (newSubId == mDefaultDataSubId) {
    135                         newDefaultDataPhoneId = phoneId;
    136                     }
    137                 }
    138                 mDefaultDataPhoneId = newDefaultDataPhoneId;
    139             }
    140         }
    141     };
    142 
    143     private final BroadcastReceiver mDefaultDataSubscriptionChangedReceiver =
    144             new BroadcastReceiver() {
    145         @Override
    146         public void onReceive(Context context, Intent intent) {
    147             final int newDefaultDataSubId = mSubscriptionController.getDefaultDataSubId();
    148             synchronized (mLock) {
    149                 if (mDefaultDataSubId != newDefaultDataSubId) {
    150                     log("Default changed " + mDefaultDataSubId + "->" + newDefaultDataSubId);
    151                     final int oldDefaultDataSubId = mDefaultDataSubId;
    152                     final int oldDefaultDataPhoneId = mDefaultDataPhoneId;
    153                     mDefaultDataSubId = newDefaultDataSubId;
    154 
    155                     int newDefaultDataPhoneId =
    156                             mSubscriptionController.getPhoneId(INVALID_SUBSCRIPTION_ID);
    157                     if (newDefaultDataSubId != INVALID_SUBSCRIPTION_ID) {
    158                         for (int phoneId = 0; phoneId < mPhoneSubId.length; phoneId++) {
    159                             if (mPhoneSubId[phoneId] == newDefaultDataSubId) {
    160                                 newDefaultDataPhoneId = phoneId;
    161                                 if (VDBG) log("newDefaultDataPhoneId=" + newDefaultDataPhoneId);
    162                                 break;
    163                             }
    164                         }
    165                     }
    166                     if (newDefaultDataPhoneId != oldDefaultDataPhoneId) {
    167                         log("Default phoneId changed " + oldDefaultDataPhoneId + "->" +
    168                                 newDefaultDataPhoneId + ", " +
    169                                 (invalidPhoneId(oldDefaultDataPhoneId) ?
    170                                  0 :
    171                                  mDefaultDataSubChangedRegistrants[oldDefaultDataPhoneId].size()) +
    172                                 "," + (invalidPhoneId(newDefaultDataPhoneId) ?
    173                                   0 :
    174                                   mDefaultDataSubChangedRegistrants[newDefaultDataPhoneId].size()) +
    175                                 " registrants");
    176                         mDefaultDataPhoneId = newDefaultDataPhoneId;
    177                         if (!invalidPhoneId(oldDefaultDataPhoneId)) {
    178                             mDefaultDataSubChangedRegistrants[oldDefaultDataPhoneId].
    179                                     notifyRegistrants();
    180                         }
    181                         if (!invalidPhoneId(newDefaultDataPhoneId)) {
    182                             mDefaultDataSubChangedRegistrants[newDefaultDataPhoneId].
    183                                     notifyRegistrants();
    184                         }
    185                     }
    186                 }
    187             }
    188         }
    189     };
    190 
    191     public void registerForSubscriptionChanged(int phoneId, Handler h, int what, Object o) {
    192         if (invalidPhoneId(phoneId)) {
    193             throw new IllegalArgumentException("Invalid PhoneId");
    194         }
    195         Registrant r = new Registrant(h, what, o);
    196         mSubscriptionsChangedRegistrants[phoneId].add(r);
    197         r.notifyRegistrant();
    198     }
    199 
    200     public void unregisterForSubscriptionChanged(int phoneId, Handler h) {
    201         if (invalidPhoneId(phoneId)) {
    202             throw new IllegalArgumentException("Invalid PhoneId");
    203         }
    204         mSubscriptionsChangedRegistrants[phoneId].remove(h);
    205     }
    206 
    207     public void registerForDefaultDataSubscriptionChanged(int phoneId, Handler h, int what,
    208             Object o) {
    209         if (invalidPhoneId(phoneId)) {
    210             throw new IllegalArgumentException("Invalid PhoneId");
    211         }
    212         Registrant r = new Registrant(h, what, o);
    213         mDefaultDataSubChangedRegistrants[phoneId].add(r);
    214         r.notifyRegistrant();
    215     }
    216 
    217     public void unregisterForDefaultDataSubscriptionChanged(int phoneId, Handler h) {
    218         if (invalidPhoneId(phoneId)) {
    219             throw new IllegalArgumentException("Invalid PhoneId");
    220         }
    221         mDefaultDataSubChangedRegistrants[phoneId].remove(h);
    222     }
    223 
    224     private boolean invalidPhoneId(int phoneId) {
    225         if (phoneId >= 0 && phoneId < mPhoneSubId.length) return false;
    226         return true;
    227     }
    228 
    229     private void log(String s) {
    230         Rlog.d(LOG_TAG, s);
    231         mLocalLog.log(s);
    232     }
    233 
    234     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
    235         synchronized (mLock) {
    236             mLocalLog.dump(fd, printWriter, args);
    237         }
    238     }
    239 }
    240