• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SubscriptionMonitor(ITelephonyRegistry tr, Context context, SubscriptionController subscriptionController, int numPhones)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
SubscriptionMonitor()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 
registerForSubscriptionChanged(int phoneId, Handler h, int what, Object o)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 
unregisterForSubscriptionChanged(int phoneId, Handler h)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 
registerForDefaultDataSubscriptionChanged(int phoneId, Handler h, int what, Object o)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 
unregisterForDefaultDataSubscriptionChanged(int phoneId, Handler h)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 
invalidPhoneId(int phoneId)224     private boolean invalidPhoneId(int phoneId) {
225         if (phoneId >= 0 && phoneId < mPhoneSubId.length) return false;
226         return true;
227     }
228 
log(String s)229     private void log(String s) {
230         Rlog.d(LOG_TAG, s);
231         mLocalLog.log(s);
232     }
233 
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)234     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
235         synchronized (mLock) {
236             mLocalLog.dump(fd, printWriter, args);
237         }
238     }
239 }
240