blob: 050cea79621a2a452e5ebc66a04f187b9f2c5dfe [file] [log] [blame]
/*
* Copyright (C) 2021 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.qns;
import static android.telephony.SubscriptionManager.EXTRA_SLOT_INDEX;
import static android.telephony.ims.ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED;
import static android.telephony.ims.ImsMmTelManager.WIFI_MODE_WIFI_ONLY;
import static android.telephony.ims.ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ProvisioningManager;
import android.util.Log;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.TelephonyIntents;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/** QnsEventDispatcher Delivers Broadcasted Intent & change on setting to registered Handlers. */
public class QnsEventDispatcher {
@IntDef(
prefix = {"QNS_EVENT_"},
value = {
QNS_EVENT_BASE,
QNS_EVENT_CARRIER_CONFIG_CHANGED,
QNS_EVENT_CARRIER_CONFIG_UNKNOWN_CARRIER,
QNS_EVENT_WIFI_DISABLING,
QNS_EVENT_WIFI_AP_CHANGED,
QNS_EVENT_APM_DISABLED,
QNS_EVENT_APM_ENABLED,
QNS_EVENT_WFC_ENABLED,
QNS_EVENT_WFC_DISABLED,
QNS_EVENT_WFC_MODE_TO_WIFI_ONLY,
QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED,
QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED,
QNS_EVENT_WFC_ROAMING_ENABLED,
QNS_EVENT_WFC_ROAMING_DISABLED,
QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY,
QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED,
QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED,
QNS_EVENT_CROSS_SIM_CALLING_ENABLED,
QNS_EVENT_CROSS_SIM_CALLING_DISABLED,
QNS_EVENT_EMERGENCY_CALLBACK_MODE_ON,
QNS_EVENT_EMERGENCY_CALLBACK_MODE_OFF,
QNS_EVENT_WFC_PLATFORM_ENABLED,
QNS_EVENT_WFC_PLATFORM_DISABLED,
QNS_EVENT_SIM_ABSENT,
QNS_EVENT_SIM_LOADED,
QNS_EVENT_WIFI_ENABLED,
})
public @interface QnsEventType {}
public static final int QNS_EVENT_BASE = 0;
public static final int QNS_EVENT_CARRIER_CONFIG_CHANGED = QNS_EVENT_BASE + 1;
public static final int QNS_EVENT_CARRIER_CONFIG_UNKNOWN_CARRIER = QNS_EVENT_BASE + 2;
public static final int QNS_EVENT_WIFI_DISABLING = QNS_EVENT_BASE + 3;
public static final int QNS_EVENT_WIFI_AP_CHANGED = QNS_EVENT_BASE + 4;
public static final int QNS_EVENT_APM_DISABLED = QNS_EVENT_BASE + 5;
public static final int QNS_EVENT_APM_ENABLED = QNS_EVENT_BASE + 6;
public static final int QNS_EVENT_WFC_ENABLED = QNS_EVENT_BASE + 7;
public static final int QNS_EVENT_WFC_DISABLED = QNS_EVENT_BASE + 8;
public static final int QNS_EVENT_WFC_MODE_TO_WIFI_ONLY = QNS_EVENT_BASE + 9;
public static final int QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED = QNS_EVENT_BASE + 10;
public static final int QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED = QNS_EVENT_BASE + 11;
public static final int QNS_EVENT_WFC_ROAMING_ENABLED = QNS_EVENT_BASE + 12;
public static final int QNS_EVENT_WFC_ROAMING_DISABLED = QNS_EVENT_BASE + 13;
public static final int QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY = QNS_EVENT_BASE + 14;
public static final int QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED = QNS_EVENT_BASE + 15;
public static final int QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED = QNS_EVENT_BASE + 16;
public static final int QNS_EVENT_CROSS_SIM_CALLING_ENABLED = QNS_EVENT_BASE + 17;
public static final int QNS_EVENT_CROSS_SIM_CALLING_DISABLED = QNS_EVENT_BASE + 18;
public static final int QNS_EVENT_EMERGENCY_CALLBACK_MODE_ON = QNS_EVENT_BASE + 19;
public static final int QNS_EVENT_EMERGENCY_CALLBACK_MODE_OFF = QNS_EVENT_BASE + 20;
public static final int QNS_EVENT_WFC_PLATFORM_ENABLED = QNS_EVENT_BASE + 21;
public static final int QNS_EVENT_WFC_PLATFORM_DISABLED = QNS_EVENT_BASE + 22;
public static final int QNS_EVENT_SIM_ABSENT = QNS_EVENT_BASE + 23;
public static final int QNS_EVENT_SIM_LOADED = QNS_EVENT_BASE + 24;
public static final int QNS_EVENT_WIFI_ENABLED = QNS_EVENT_BASE + 25;
private static final int EVENT_CREATE_PROVISIONING_LISTENER = QNS_EVENT_BASE + 200;
private static final int EVENT_PROVISIONING_INFO_CHANGED = QNS_EVENT_BASE + 201;
private static final Map<Integer, QnsEventDispatcher> sInstances = new ConcurrentHashMap<>();
private static Boolean sIsAirplaneModeOn;
private static int mWiFiState = WifiManager.WIFI_STATE_UNKNOWN;
private final String LOG_TAG;
private final Context mContext;
private final int mSlotIndex;
SparseArray<Set<Handler>> mEventHandlers = new SparseArray<>();
private int mSubId;
private Uri mCrossSimCallingUri;
private Uri mWfcEnabledUri;
private Uri mWfcModeUri;
private Uri mWfcRoamingEnabledUri;
private Uri mWfcRoamingModeUri;
@VisibleForTesting UserSettingObserver mUserSettingObserver;
private HandlerThread mUserSettingHandlerThread;
boolean mLastWfcEnabledByPlatform = false;
boolean mLastCrossSimCallingEnabled = false;
boolean mLastWfcEnabled = false;
int mLastWfcMode = WIFI_MODE_CELLULAR_PREFERRED;
boolean mLastWfcRoamingEnabled = false;
int mLastWfcModeRoaming = WIFI_MODE_WIFI_PREFERRED;
protected QnsProvisioningListener mQnsProvisioningListener;
private QnsProvisioningListener.QnsProvisioningInfo mLastProvisioningInfo;
private final QnsEventDispatcherHandler mQnsEventDispatcherHandler;
@VisibleForTesting
final BroadcastReceiver mIntentReceiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
int event;
Log.d(LOG_TAG, "onReceive: " + action);
switch (action) {
case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
int slotId =
intent.getIntExtra(
CarrierConfigManager.EXTRA_SLOT_INDEX,
SubscriptionManager.INVALID_SIM_SLOT_INDEX);
int carrierId =
intent.getIntExtra(
TelephonyManager.EXTRA_CARRIER_ID,
TelephonyManager.UNKNOWN_CARRIER_ID);
onCarrierConfigChanged(context, slotId, carrierId);
break;
case TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED:
case TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED:
slotId =
intent.getIntExtra(
CarrierConfigManager.EXTRA_SLOT_INDEX,
SubscriptionManager.INVALID_SIM_SLOT_INDEX);
int simState =
intent.getIntExtra(
TelephonyManager.EXTRA_SIM_STATE,
TelephonyManager.SIM_STATE_UNKNOWN);
onSimStateChanged(slotId, simState);
break;
case Intent.ACTION_AIRPLANE_MODE_CHANGED:
Boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
if (sIsAirplaneModeOn != null
&& sIsAirplaneModeOn.equals(isAirplaneModeOn)) {
// no change in apm state
break;
}
sIsAirplaneModeOn = isAirplaneModeOn;
event =
sIsAirplaneModeOn
? QNS_EVENT_APM_ENABLED
: QNS_EVENT_APM_DISABLED;
for (Map.Entry<Integer, QnsEventDispatcher> entry :
sInstances.entrySet()) {
QnsEventDispatcher instance = entry.getValue();
instance.updateHandlers(event);
}
break;
case WifiManager.WIFI_STATE_CHANGED_ACTION:
int wifiState =
intent.getIntExtra(
WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN);
if (wifiState != mWiFiState) {
mWiFiState = wifiState;
if (wifiState == WifiManager.WIFI_STATE_DISABLING) {
event = QNS_EVENT_WIFI_DISABLING;
} else if (wifiState == WifiManager.WIFI_STATE_ENABLED) {
event = QNS_EVENT_WIFI_ENABLED;
} else {
break;
}
for (Map.Entry<Integer, QnsEventDispatcher> entry :
sInstances.entrySet()) {
QnsEventDispatcher instance = entry.getValue();
instance.updateHandlers(event);
}
}
break;
case TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED:
boolean emergencyMode =
intent.getBooleanExtra(
TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false);
event =
emergencyMode
? QNS_EVENT_EMERGENCY_CALLBACK_MODE_ON
: QNS_EVENT_EMERGENCY_CALLBACK_MODE_OFF;
int slotIndex = intent.getIntExtra(EXTRA_SLOT_INDEX, 0);
getInstance(mContext, slotIndex).updateHandlers(event);
break;
}
}
};
private QnsEventDispatcher(@NonNull Context context, int slotIndex) {
mContext = context;
mSlotIndex = slotIndex;
LOG_TAG = QnsEventDispatcher.class.getSimpleName() + "[" + slotIndex + "]";
mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
final ContentResolver cr = mContext.getContentResolver();
int airplaneMode = Settings.Global.getInt(cr, Settings.Global.AIRPLANE_MODE_ON, 0);
sIsAirplaneModeOn = (airplaneMode == 1);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
intentFilter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
intentFilter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
mContext.registerReceiver(mIntentReceiver, intentFilter);
HandlerThread handlerThread =
new HandlerThread(QnsEventDispatcher.class.getSimpleName() + slotIndex);
handlerThread.start();
mQnsEventDispatcherHandler = new QnsEventDispatcherHandler(handlerThread.getLooper());
Message msg = mQnsEventDispatcherHandler.obtainMessage(EVENT_CREATE_PROVISIONING_LISTENER);
mQnsEventDispatcherHandler.sendMessage(msg);
}
public static QnsEventDispatcher getInstance(@NonNull Context context, int slotId) {
return sInstances.computeIfAbsent(slotId, k -> new QnsEventDispatcher(context, slotId));
}
private synchronized void onCarrierConfigChanged(Context context, int slotId, int carrierId) {
if (slotId != mSlotIndex) {
return;
}
Log.d(LOG_TAG, "onCarrierConfigChanged");
int subId = QnsUtils.getSubId(context, slotId);
if (subId != mSubId) {
unregisterContentObserver();
mSubId = subId;
registerContentObserver();
}
notifyWfcEnabledByPlatform();
notifyCurrentSetting(mCrossSimCallingUri, true);
notifyCurrentSetting(mWfcEnabledUri, true);
notifyCurrentSetting(mWfcModeUri, true);
notifyCurrentSetting(mWfcRoamingEnabledUri, true);
notifyCurrentSetting(mWfcRoamingModeUri, true);
int event;
if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
event = QNS_EVENT_CARRIER_CONFIG_CHANGED;
} else {
event = QNS_EVENT_CARRIER_CONFIG_UNKNOWN_CARRIER;
}
updateHandlers(event);
}
public synchronized void registerEvent(List<Integer> events, Handler handler) {
for (@QnsEventType int event : events) {
if (mEventHandlers.contains(event)) {
mEventHandlers.get(event).add(handler);
} else {
Set<Handler> handlers = new HashSet<>();
handlers.add(handler);
mEventHandlers.append(event, handlers);
}
}
notifyImmediately(events, handler);
}
private void onSimStateChanged(int slotId, int simState) {
if (slotId != mSlotIndex) {
return;
}
if (simState == TelephonyManager.SIM_STATE_ABSENT) {
updateHandlers(QNS_EVENT_SIM_ABSENT);
} else if (simState == TelephonyManager.SIM_STATE_LOADED) {
updateHandlers(QNS_EVENT_SIM_LOADED);
}
}
private synchronized void notifyImmediately(List<Integer> events, Handler handler) {
boolean bWfcPlatformSetting = false;
boolean bWfcSetting = false;
boolean bWfcModeSetting = false;
boolean bWfcRoamingSetting = false;
boolean bWfcRoamingModeSetting = false;
boolean bCrossSimSetting = false;
for (@QnsEventType int event : events) {
switch (event) {
case QNS_EVENT_WFC_PLATFORM_ENABLED:
case QNS_EVENT_WFC_PLATFORM_DISABLED:
bWfcPlatformSetting = true;
break;
case QNS_EVENT_WFC_ENABLED:
case QNS_EVENT_WFC_DISABLED:
bWfcSetting = true;
break;
case QNS_EVENT_WFC_ROAMING_ENABLED:
case QNS_EVENT_WFC_ROAMING_DISABLED:
bWfcRoamingSetting = true;
break;
case QNS_EVENT_WFC_MODE_TO_WIFI_ONLY:
case QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED:
case QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED:
bWfcModeSetting = true;
break;
case QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY:
case QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED:
case QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED:
bWfcRoamingModeSetting = true;
case QnsEventDispatcher.QNS_EVENT_CROSS_SIM_CALLING_ENABLED:
case QnsEventDispatcher.QNS_EVENT_CROSS_SIM_CALLING_DISABLED:
bCrossSimSetting = true;
break;
}
}
if (bWfcPlatformSetting) {
if (mLastWfcEnabledByPlatform) {
updateHandler(handler, QNS_EVENT_WFC_PLATFORM_ENABLED);
} else {
updateHandler(handler, QNS_EVENT_WFC_PLATFORM_DISABLED);
}
// checks again whether setting is changed.
notifyWfcEnabledByPlatform();
}
if (bWfcSetting) {
if (mLastWfcEnabled) {
updateHandler(handler, QNS_EVENT_WFC_ENABLED);
} else {
updateHandler(handler, QNS_EVENT_WFC_DISABLED);
}
// checks again whether setting is changed.
notifyCurrentSetting(mWfcEnabledUri, false);
}
if (bWfcModeSetting) {
switch (mLastWfcMode) {
case WIFI_MODE_WIFI_ONLY:
updateHandler(handler, QNS_EVENT_WFC_MODE_TO_WIFI_ONLY);
break;
case WIFI_MODE_CELLULAR_PREFERRED:
updateHandler(handler, QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED);
break;
case WIFI_MODE_WIFI_PREFERRED:
updateHandler(handler, QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED);
break;
}
// checks again whether setting is changed.
notifyCurrentSetting(mWfcModeUri, false);
}
if (bWfcRoamingSetting) {
if (mLastWfcRoamingEnabled) {
updateHandler(handler, QNS_EVENT_WFC_ROAMING_ENABLED);
} else {
updateHandler(handler, QNS_EVENT_WFC_ROAMING_DISABLED);
}
// checks again whether setting is changed.
notifyCurrentSetting(mWfcRoamingEnabledUri, false);
}
if (bWfcRoamingModeSetting) {
switch (mLastWfcModeRoaming) {
case WIFI_MODE_WIFI_ONLY:
updateHandler(handler, QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY);
break;
case WIFI_MODE_CELLULAR_PREFERRED:
updateHandler(handler, QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED);
break;
case WIFI_MODE_WIFI_PREFERRED:
updateHandler(handler, QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED);
break;
}
// checks again whether setting is changed.
notifyCurrentSetting(mWfcRoamingModeUri, false);
}
if (bCrossSimSetting) {
if (mLastCrossSimCallingEnabled) {
updateHandler(handler, QNS_EVENT_CROSS_SIM_CALLING_ENABLED);
} else {
updateHandler(handler, QNS_EVENT_CROSS_SIM_CALLING_DISABLED);
}
// checks again whether setting is changed.
notifyCurrentSetting(mCrossSimCallingUri, false);
}
}
public synchronized void unregisterEvent(Handler handler) {
for (int i = 0; i < mEventHandlers.size(); i++) {
Set<Handler> handlers = mEventHandlers.valueAt(i);
handlers.remove(handler);
if (handlers.isEmpty()) {
mEventHandlers.delete(mEventHandlers.keyAt(i));
i--;
}
}
if (mEventHandlers.size() == 0) {
dispose();
}
}
public void dispose() {
try {
mContext.unregisterReceiver(mIntentReceiver);
} catch (IllegalArgumentException ignored) {
}
if (mUserSettingObserver != null) {
mContext.getContentResolver().unregisterContentObserver(mUserSettingObserver);
}
if (mUserSettingHandlerThread != null) {
mUserSettingHandlerThread.quit();
}
if (mQnsProvisioningListener != null) {
mQnsProvisioningListener.unregisterProvisioningItemInfoChanged(
mQnsEventDispatcherHandler);
}
sInstances.remove(mSlotIndex, this);
}
private synchronized void unregisterContentObserver() {
if (mUserSettingObserver != null) {
mContext.getContentResolver().unregisterContentObserver(mUserSettingObserver);
}
mCrossSimCallingUri = null;
mWfcEnabledUri = null;
mWfcModeUri = null;
mWfcRoamingEnabledUri = null;
mWfcRoamingModeUri = null;
}
private void registerContentObserver() {
// Register for content observer
if (mUserSettingObserver == null) {
Log.d(LOG_TAG, "create mUserSettingObserver");
mUserSettingHandlerThread = new HandlerThread(QnsEventDispatcher.class.getSimpleName());
mUserSettingHandlerThread.start();
Looper looper = mUserSettingHandlerThread.getLooper();
Handler handler = new Handler(looper);
mUserSettingObserver = new UserSettingObserver(handler);
// init
mLastWfcEnabledByPlatform = QnsUtils.isWfcEnabledByPlatform(mContext, mSlotIndex);
mLastCrossSimCallingEnabled = QnsUtils.isCrossSimCallingEnabled(mContext, mSlotIndex);
mLastWfcEnabled = QnsUtils.isWfcEnabled(mContext, mSlotIndex, false);
mLastWfcMode = QnsUtils.getWfcMode(mContext, mSlotIndex, false);
mLastWfcRoamingEnabled = QnsUtils.isWfcEnabled(mContext, mSlotIndex, true);
mLastWfcModeRoaming = QnsUtils.getWfcMode(mContext, mSlotIndex, true);
}
if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return;
}
StringBuilder sb = new StringBuilder("registerContentObserver");
sb.append(" subId:").append(mSubId);
ContentResolver resolver = mContext.getContentResolver();
// Update current Cross Sim Calling setting
Uri crossSimCallingUri = getUri(SubscriptionManager.CROSS_SIM_ENABLED_CONTENT_URI, mSubId);
if (!crossSimCallingUri.equals(mCrossSimCallingUri)) {
mCrossSimCallingUri = crossSimCallingUri;
sb.append(" crossSimCallingUri/").append(mSubId);
resolver.registerContentObserver(mCrossSimCallingUri, true, mUserSettingObserver);
}
// Update current Wi-Fi Calling setting
Uri wfcEnabledUri = getUri(SubscriptionManager.WFC_ENABLED_CONTENT_URI, mSubId);
if (!wfcEnabledUri.equals(mWfcEnabledUri)) {
mWfcEnabledUri = wfcEnabledUri;
sb.append(" wfcEnabledUri/").append(mSubId);
resolver.registerContentObserver(mWfcEnabledUri, true, mUserSettingObserver);
}
// Update current Wi-Fi Calling Mode setting
Uri wfcModeUri = getUri(SubscriptionManager.WFC_MODE_CONTENT_URI, mSubId);
if (!wfcModeUri.equals(mWfcModeUri)) {
mWfcModeUri = wfcModeUri;
sb.append(" wfcModeUri/").append(mSubId);
resolver.registerContentObserver(mWfcModeUri, true, mUserSettingObserver);
}
// Update current Wi-Fi Calling setting for roaming
Uri wfcRoamEnabledUri = getUri(SubscriptionManager.WFC_ROAMING_ENABLED_CONTENT_URI, mSubId);
if (!wfcRoamEnabledUri.equals(mWfcRoamingEnabledUri)) {
mWfcRoamingEnabledUri = wfcRoamEnabledUri;
sb.append(" wfcRoamEnabledUri/").append(mSubId);
resolver.registerContentObserver(mWfcRoamingEnabledUri, true, mUserSettingObserver);
}
// Update current Wi-Fi Calling Mode setting for roaming
Uri wfcRoamingModeUri = getUri(SubscriptionManager.WFC_ROAMING_MODE_CONTENT_URI, mSubId);
if (!wfcRoamingModeUri.equals(mWfcRoamingModeUri)) {
mWfcRoamingModeUri = wfcRoamingModeUri;
sb.append(" wfcRoamingModeUri/").append(mSubId);
resolver.registerContentObserver(mWfcRoamingModeUri, true, mUserSettingObserver);
}
Log.d(LOG_TAG, sb.toString());
}
private Uri getUri(Uri uri, int subId) {
return Uri.withAppendedPath(uri, String.valueOf(subId));
}
void notifyCurrentSetting(Uri uri, boolean bForceUpdate) {
if (uri == null) {
return;
}
try {
String uriString = uri.getPath();
int subIndex = Integer.parseInt(uriString.substring(uriString.lastIndexOf('/') + 1));
int slotIndex = SubscriptionManager.getSlotIndex(subIndex);
int event = QNS_EVENT_BASE;
if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
Log.e(LOG_TAG, "Invalid slot index: " + slotIndex);
return;
}
StringBuilder sb = new StringBuilder("notifyCurrentSetting");
sb.append(", bForceUpdate:").append(bForceUpdate);
Log.d(LOG_TAG, "CrossSimCallingUri:" + mCrossSimCallingUri);
Log.d(LOG_TAG, "mWfcEnabledUri:" + mWfcEnabledUri);
Log.d(LOG_TAG, "mWfcModeUri:" + mWfcModeUri);
Log.d(LOG_TAG, "mWfcRoamingEnabledUri:" + mWfcRoamingEnabledUri);
Log.d(LOG_TAG, "mWfcRoamingEnabledUri:" + mWfcRoamingEnabledUri);
if (uri.equals(mCrossSimCallingUri)) {
boolean isCrossSimCallingEnabled =
QnsUtils.isCrossSimCallingEnabled(mContext, slotIndex);
if (mLastCrossSimCallingEnabled != isCrossSimCallingEnabled || bForceUpdate) {
if (isCrossSimCallingEnabled) {
event = QNS_EVENT_CROSS_SIM_CALLING_ENABLED;
} else {
event = QNS_EVENT_CROSS_SIM_CALLING_DISABLED;
}
mLastCrossSimCallingEnabled = isCrossSimCallingEnabled;
sb.append(", isCrossSimCallingEnabled:").append(isCrossSimCallingEnabled);
Log.d(LOG_TAG, sb.toString());
updateHandlers(event);
}
} else if (uri.equals(mWfcEnabledUri)) {
boolean isWfcEnabled = QnsUtils.isWfcEnabled(mContext, slotIndex, false);
if (mLastWfcEnabled != isWfcEnabled || bForceUpdate) {
if (isWfcEnabled) {
event = QNS_EVENT_WFC_ENABLED;
} else {
event = QNS_EVENT_WFC_DISABLED;
}
mLastWfcEnabled = isWfcEnabled;
sb.append(", isWfcEnabled:").append(isWfcEnabled);
Log.d(LOG_TAG, sb.toString());
updateHandlers(event);
}
} else if (uri.equals(mWfcModeUri)) {
int wfcMode = QnsUtils.getWfcMode(mContext, slotIndex, false);
if (mLastWfcMode != wfcMode || bForceUpdate) {
switch (wfcMode) {
case WIFI_MODE_WIFI_ONLY:
event = QNS_EVENT_WFC_MODE_TO_WIFI_ONLY;
break;
case WIFI_MODE_CELLULAR_PREFERRED:
event = QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED;
break;
case WIFI_MODE_WIFI_PREFERRED:
event = QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED;
break;
}
mLastWfcMode = wfcMode;
sb.append(", wfcMode:").append(wfcMode);
Log.d(LOG_TAG, sb.toString());
updateHandlers(event);
}
} else if (uri.equals(mWfcRoamingEnabledUri)) {
boolean isWfcRoamingEnabled = QnsUtils.isWfcEnabled(mContext, slotIndex, true);
if (mLastWfcRoamingEnabled != isWfcRoamingEnabled || bForceUpdate) {
if (isWfcRoamingEnabled) {
event = QNS_EVENT_WFC_ROAMING_ENABLED;
} else {
event = QNS_EVENT_WFC_ROAMING_DISABLED;
}
mLastWfcRoamingEnabled = isWfcRoamingEnabled;
sb.append(", isWfcRoamingEnabled:").append(isWfcRoamingEnabled);
Log.d(LOG_TAG, sb.toString());
updateHandlers(event);
}
} else if (uri.equals(mWfcRoamingModeUri)) {
int wfcModeRoaming = QnsUtils.getWfcMode(mContext, slotIndex, true);
if (mLastWfcModeRoaming != wfcModeRoaming || bForceUpdate) {
switch (wfcModeRoaming) {
case WIFI_MODE_WIFI_ONLY:
event = QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY;
break;
case WIFI_MODE_CELLULAR_PREFERRED:
event = QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED;
break;
case WIFI_MODE_WIFI_PREFERRED:
event = QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED;
break;
}
mLastWfcModeRoaming = wfcModeRoaming;
sb.append(", wfcModeRoaming:").append(wfcModeRoaming);
Log.d(LOG_TAG, sb.toString());
updateHandlers(event);
}
} else {
Log.e(LOG_TAG, "Unknown Uri : " + uri);
}
} catch (Exception e) {
Log.e(LOG_TAG, "notifyCurrentSetting got exception:" + e);
e.printStackTrace();
}
}
void notifyWfcEnabledByPlatform() {
boolean isWfcEnabledByPlatform = QnsUtils.isWfcEnabledByPlatform(mContext, mSlotIndex);
if (mLastWfcEnabledByPlatform != isWfcEnabledByPlatform) {
mLastWfcEnabledByPlatform = isWfcEnabledByPlatform;
Log.d(LOG_TAG, "notifyWfcEnabledByPlatform:" + isWfcEnabledByPlatform);
if (isWfcEnabledByPlatform) {
updateHandlers(QNS_EVENT_WFC_PLATFORM_ENABLED);
} else {
updateHandlers(QNS_EVENT_WFC_PLATFORM_DISABLED);
}
}
}
private synchronized void updateHandler(Handler handler, int event) {
try {
if (mEventHandlers.get(event).contains(handler)) {
Log.d(LOG_TAG, "Updating handler for the event: " + event);
handler.obtainMessage(event).sendToTarget();
}
} catch (Exception e) {
Log.e(LOG_TAG, "updateHandler got exception e:" + e);
}
}
private synchronized void updateHandlers(int event) {
if (mEventHandlers.contains(event)) {
Log.d(LOG_TAG, "Updating handlers for the event: " + event);
for (Handler handler : mEventHandlers.get(event)) {
handler.obtainMessage(event).sendToTarget();
}
}
}
@VisibleForTesting
class UserSettingObserver extends ContentObserver {
UserSettingObserver(Handler h) {
super(h);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
Log.d(LOG_TAG, "onUserSettingChanged");
onUserSettingChanged(uri);
}
}
private synchronized void onUserSettingChanged(Uri uri) {
if (mCrossSimCallingUri.equals(uri)) {
notifyCurrentSetting(uri, false);
} else if (mWfcEnabledUri.equals(uri)) {
// checks platform changes first.
notifyWfcEnabledByPlatform();
notifyCurrentSetting(uri, false);
} else if (mWfcModeUri.equals(uri)) {
notifyCurrentSetting(uri, false);
} else if (mWfcRoamingEnabledUri.equals(uri)) {
// checks platform changes first.
notifyWfcEnabledByPlatform();
notifyCurrentSetting(uri, false);
} else if (mWfcRoamingModeUri.equals(uri)) {
notifyCurrentSetting(uri, false);
}
}
private class QnsEventDispatcherHandler extends Handler {
/**
* Use the provided {@link Looper} instead of the default one.
*
* @param looper The looper, must not be null.
*/
public QnsEventDispatcherHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message message) {
Log.d(LOG_TAG, "handleMessage msg=" + message.what);
AsyncResult ar = (AsyncResult) message.obj;
switch (message.what) {
case EVENT_CREATE_PROVISIONING_LISTENER:
onCreateProvisioningListener();
break;
case EVENT_PROVISIONING_INFO_CHANGED:
onProvisioningInfoChanged(
(QnsProvisioningListener.QnsProvisioningInfo) ar.result);
break;
default:
break;
}
}
}
private void onCreateProvisioningListener() {
if (mQnsProvisioningListener != null) {
return;
}
Log.d(LOG_TAG, "onCreateProvisioningListener");
mLastProvisioningInfo = new QnsProvisioningListener.QnsProvisioningInfo();
mQnsProvisioningListener = QnsProvisioningListener.getInstance(mContext, mSlotIndex);
if (mQnsProvisioningListener != null) {
mQnsProvisioningListener.registerProvisioningItemInfoChanged(
mQnsEventDispatcherHandler, EVENT_PROVISIONING_INFO_CHANGED, null, true);
}
}
private synchronized void onProvisioningInfoChanged(
QnsProvisioningListener.QnsProvisioningInfo info) {
Log.d(LOG_TAG, "onProvisioningInfoChanged info:" + info);
if (!info.equalsIntegerItem(
mLastProvisioningInfo,
ProvisioningManager.KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE)) {
Log.d(
LOG_TAG,
"onProvisioningInfoChanged, KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE("
+ ProvisioningManager.KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE
+ ") is provisioned to "
+ info.getIntegerItem(
ProvisioningManager
.KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE));
// checks platform changes first.
notifyWfcEnabledByPlatform();
notifyCurrentSetting(mWfcRoamingEnabledUri, false);
}
if (!info.equalsIntegerItem(
mLastProvisioningInfo, ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE)) {
Log.d(
LOG_TAG,
"onProvisioningInfoChanged, KEY_VOICE_OVER_WIFI_MODE_OVERRIDE("
+ ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE
+ ") is provisioned to "
+ info.getIntegerItem(
ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE));
notifyCurrentSetting(mWfcModeUri, false);
}
if (!info.equalsIntegerItem(
mLastProvisioningInfo, ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE)) {
Log.d(
LOG_TAG,
"onProvisioningInfoChanged, KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE("
+ ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE
+ ") is provisioned to "
+ info.getIntegerItem(
ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE));
// checks platform changes first.
notifyWfcEnabledByPlatform();
notifyCurrentSetting(mWfcEnabledUri, false);
}
mLastProvisioningInfo = info;
}
public boolean isAirplaneModeToggleOn() {
return sIsAirplaneModeOn;
}
}