blob: 4307875374fe0c0ea76e6259f489ff37afffd528 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony;
import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.util.LocalLog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.PhoneConstants;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.IllegalArgumentException;
/**
* Utility singleton to monitor subscription changes and help people act on them.
* Uses Registrant model to post messages to handlers.
*
*/
public class SubscriptionMonitor {
private final RegistrantList mSubscriptionsChangedRegistrants[];
private final RegistrantList mDefaultDataSubChangedRegistrants[];
private final SubscriptionController mSubscriptionController;
private final Context mContext;
private final int mPhoneSubId[];
private int mDefaultDataSubId;
private int mDefaultDataPhoneId;
private final Object mLock = new Object();
private final static boolean VDBG = true;
private final static String LOG_TAG = "SubscriptionMonitor";
private final static int MAX_LOGLINES = 100;
private final LocalLog mLocalLog = new LocalLog(MAX_LOGLINES);
public SubscriptionMonitor(ITelephonyRegistry tr, Context context,
SubscriptionController subscriptionController, int numPhones) {
try {
tr.addOnSubscriptionsChangedListener("SubscriptionMonitor",
mSubscriptionsChangedListener);
} catch (RemoteException e) {
}
mSubscriptionController = subscriptionController;
mContext = context;
mSubscriptionsChangedRegistrants = new RegistrantList[numPhones];
mDefaultDataSubChangedRegistrants = new RegistrantList[numPhones];
mPhoneSubId = new int[numPhones];
mDefaultDataSubId = mSubscriptionController.getDefaultDataSubId();
mDefaultDataPhoneId = mSubscriptionController.getPhoneId(mDefaultDataSubId);
for (int phoneId = 0; phoneId < numPhones; phoneId++) {
mSubscriptionsChangedRegistrants[phoneId] = new RegistrantList();
mDefaultDataSubChangedRegistrants[phoneId] = new RegistrantList();
mPhoneSubId[phoneId] = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
}
mContext.registerReceiver(mDefaultDataSubscriptionChangedReceiver,
new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
}
@VisibleForTesting
public SubscriptionMonitor() {
mSubscriptionsChangedRegistrants = null;
mDefaultDataSubChangedRegistrants = null;
mSubscriptionController = null;
mContext = null;
mPhoneSubId = null;
}
private final IOnSubscriptionsChangedListener mSubscriptionsChangedListener =
new IOnSubscriptionsChangedListener.Stub() {
@Override
public void onSubscriptionsChanged() {
synchronized (mLock) {
int newDefaultDataPhoneId = INVALID_PHONE_INDEX;
for (int phoneId = 0; phoneId < mPhoneSubId.length; phoneId++) {
final int newSubId = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
final int oldSubId = mPhoneSubId[phoneId];
if (oldSubId != newSubId) {
log("Phone[" + phoneId + "] subId changed " + oldSubId + "->" +
newSubId + ", " +
mSubscriptionsChangedRegistrants[phoneId].size() + " registrants");
mPhoneSubId[phoneId] = newSubId;
mSubscriptionsChangedRegistrants[phoneId].notifyRegistrants();
// if the default isn't set, just move along..
if (mDefaultDataSubId == INVALID_SUBSCRIPTION_ID) continue;
// check if this affects default data
if (newSubId == mDefaultDataSubId || oldSubId == mDefaultDataSubId) {
log("mDefaultDataSubId = " + mDefaultDataSubId + ", " +
mDefaultDataSubChangedRegistrants[phoneId].size() +
" registrants");
mDefaultDataSubChangedRegistrants[phoneId].notifyRegistrants();
}
}
if (newSubId == mDefaultDataSubId) {
newDefaultDataPhoneId = phoneId;
}
}
mDefaultDataPhoneId = newDefaultDataPhoneId;
}
}
};
private final BroadcastReceiver mDefaultDataSubscriptionChangedReceiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final int newDefaultDataSubId = mSubscriptionController.getDefaultDataSubId();
synchronized (mLock) {
if (mDefaultDataSubId != newDefaultDataSubId) {
log("Default changed " + mDefaultDataSubId + "->" + newDefaultDataSubId);
final int oldDefaultDataSubId = mDefaultDataSubId;
final int oldDefaultDataPhoneId = mDefaultDataPhoneId;
mDefaultDataSubId = newDefaultDataSubId;
int newDefaultDataPhoneId =
mSubscriptionController.getPhoneId(INVALID_SUBSCRIPTION_ID);
if (newDefaultDataSubId != INVALID_SUBSCRIPTION_ID) {
for (int phoneId = 0; phoneId < mPhoneSubId.length; phoneId++) {
if (mPhoneSubId[phoneId] == newDefaultDataSubId) {
newDefaultDataPhoneId = phoneId;
if (VDBG) log("newDefaultDataPhoneId=" + newDefaultDataPhoneId);
break;
}
}
}
if (newDefaultDataPhoneId != oldDefaultDataPhoneId) {
log("Default phoneId changed " + oldDefaultDataPhoneId + "->" +
newDefaultDataPhoneId + ", " +
(invalidPhoneId(oldDefaultDataPhoneId) ?
0 :
mDefaultDataSubChangedRegistrants[oldDefaultDataPhoneId].size()) +
"," + (invalidPhoneId(newDefaultDataPhoneId) ?
0 :
mDefaultDataSubChangedRegistrants[newDefaultDataPhoneId].size()) +
" registrants");
mDefaultDataPhoneId = newDefaultDataPhoneId;
if (!invalidPhoneId(oldDefaultDataPhoneId)) {
mDefaultDataSubChangedRegistrants[oldDefaultDataPhoneId].
notifyRegistrants();
}
if (!invalidPhoneId(newDefaultDataPhoneId)) {
mDefaultDataSubChangedRegistrants[newDefaultDataPhoneId].
notifyRegistrants();
}
}
}
}
}
};
public void registerForSubscriptionChanged(int phoneId, Handler h, int what, Object o) {
if (invalidPhoneId(phoneId)) {
throw new IllegalArgumentException("Invalid PhoneId");
}
Registrant r = new Registrant(h, what, o);
mSubscriptionsChangedRegistrants[phoneId].add(r);
r.notifyRegistrant();
}
public void unregisterForSubscriptionChanged(int phoneId, Handler h) {
if (invalidPhoneId(phoneId)) {
throw new IllegalArgumentException("Invalid PhoneId");
}
mSubscriptionsChangedRegistrants[phoneId].remove(h);
}
public void registerForDefaultDataSubscriptionChanged(int phoneId, Handler h, int what,
Object o) {
if (invalidPhoneId(phoneId)) {
throw new IllegalArgumentException("Invalid PhoneId");
}
Registrant r = new Registrant(h, what, o);
mDefaultDataSubChangedRegistrants[phoneId].add(r);
r.notifyRegistrant();
}
public void unregisterForDefaultDataSubscriptionChanged(int phoneId, Handler h) {
if (invalidPhoneId(phoneId)) {
throw new IllegalArgumentException("Invalid PhoneId");
}
mDefaultDataSubChangedRegistrants[phoneId].remove(h);
}
private boolean invalidPhoneId(int phoneId) {
if (phoneId >= 0 && phoneId < mPhoneSubId.length) return false;
return true;
}
private void log(String s) {
Rlog.d(LOG_TAG, s);
mLocalLog.log(s);
}
public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
synchronized (mLock) {
mLocalLog.dump(fd, printWriter, args);
}
}
}