1 /* 2 * Copyright (C) 2021 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.telephony.qns; 18 19 import static android.telephony.SubscriptionManager.EXTRA_SLOT_INDEX; 20 import static android.telephony.ims.ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED; 21 import static android.telephony.ims.ImsMmTelManager.WIFI_MODE_WIFI_ONLY; 22 import static android.telephony.ims.ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED; 23 24 import static com.android.telephony.qns.wfc.WfcActivationHelper.ACTION_TRY_WFC_CONNECTION; 25 import static com.android.telephony.qns.wfc.WfcActivationHelper.EXTRA_SUB_ID; 26 import static com.android.telephony.qns.wfc.WfcActivationHelper.EXTRA_TRY_STATUS; 27 import static com.android.telephony.qns.wfc.WfcActivationHelper.STATUS_START; 28 29 import android.annotation.IntDef; 30 import android.content.BroadcastReceiver; 31 import android.content.ContentResolver; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.IntentFilter; 35 import android.database.ContentObserver; 36 import android.net.Uri; 37 import android.net.wifi.WifiManager; 38 import android.os.Handler; 39 import android.os.HandlerThread; 40 import android.os.Looper; 41 import android.os.Message; 42 import android.provider.Settings; 43 import android.telephony.CarrierConfigManager; 44 import android.telephony.SubscriptionManager; 45 import android.telephony.TelephonyManager; 46 import android.telephony.ims.ProvisioningManager; 47 import android.util.Log; 48 import android.util.SparseArray; 49 50 import com.android.internal.annotations.VisibleForTesting; 51 import com.android.internal.telephony.TelephonyIntents; 52 53 import java.util.HashSet; 54 import java.util.List; 55 import java.util.Set; 56 57 /** QnsEventDispatcher Delivers Broadcasted Intent & change on setting to registered Handlers. */ 58 class QnsEventDispatcher { 59 60 @IntDef( 61 prefix = {"QNS_EVENT_"}, 62 value = { 63 QNS_EVENT_BASE, 64 QNS_EVENT_CARRIER_CONFIG_CHANGED, 65 QNS_EVENT_CARRIER_CONFIG_UNKNOWN_CARRIER, 66 QNS_EVENT_WIFI_DISABLING, 67 QNS_EVENT_WIFI_AP_CHANGED, 68 QNS_EVENT_APM_DISABLED, 69 QNS_EVENT_APM_ENABLED, 70 QNS_EVENT_WFC_ENABLED, 71 QNS_EVENT_WFC_DISABLED, 72 QNS_EVENT_WFC_MODE_TO_WIFI_ONLY, 73 QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED, 74 QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED, 75 QNS_EVENT_WFC_ROAMING_ENABLED, 76 QNS_EVENT_WFC_ROAMING_DISABLED, 77 QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY, 78 QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED, 79 QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED, 80 QNS_EVENT_CROSS_SIM_CALLING_ENABLED, 81 QNS_EVENT_CROSS_SIM_CALLING_DISABLED, 82 QNS_EVENT_EMERGENCY_CALLBACK_MODE_ON, 83 QNS_EVENT_EMERGENCY_CALLBACK_MODE_OFF, 84 QNS_EVENT_WFC_PLATFORM_ENABLED, 85 QNS_EVENT_WFC_PLATFORM_DISABLED, 86 QNS_EVENT_SIM_ABSENT, 87 QNS_EVENT_SIM_LOADED, 88 QNS_EVENT_WIFI_ENABLED, 89 }) 90 @interface QnsEventType {} 91 92 static final int QNS_EVENT_BASE = 0; 93 static final int QNS_EVENT_CARRIER_CONFIG_CHANGED = QNS_EVENT_BASE + 1; 94 static final int QNS_EVENT_CARRIER_CONFIG_UNKNOWN_CARRIER = QNS_EVENT_BASE + 2; 95 static final int QNS_EVENT_WIFI_DISABLING = QNS_EVENT_BASE + 3; 96 static final int QNS_EVENT_WIFI_AP_CHANGED = QNS_EVENT_BASE + 4; 97 static final int QNS_EVENT_APM_DISABLED = QNS_EVENT_BASE + 5; 98 static final int QNS_EVENT_APM_ENABLED = QNS_EVENT_BASE + 6; 99 static final int QNS_EVENT_WFC_ENABLED = QNS_EVENT_BASE + 7; 100 static final int QNS_EVENT_WFC_DISABLED = QNS_EVENT_BASE + 8; 101 static final int QNS_EVENT_WFC_MODE_TO_WIFI_ONLY = QNS_EVENT_BASE + 9; 102 static final int QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED = QNS_EVENT_BASE + 10; 103 static final int QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED = QNS_EVENT_BASE + 11; 104 static final int QNS_EVENT_WFC_ROAMING_ENABLED = QNS_EVENT_BASE + 12; 105 static final int QNS_EVENT_WFC_ROAMING_DISABLED = QNS_EVENT_BASE + 13; 106 static final int QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY = QNS_EVENT_BASE + 14; 107 static final int QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED = QNS_EVENT_BASE + 15; 108 static final int QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED = QNS_EVENT_BASE + 16; 109 static final int QNS_EVENT_CROSS_SIM_CALLING_ENABLED = QNS_EVENT_BASE + 17; 110 static final int QNS_EVENT_CROSS_SIM_CALLING_DISABLED = QNS_EVENT_BASE + 18; 111 static final int QNS_EVENT_EMERGENCY_CALLBACK_MODE_ON = QNS_EVENT_BASE + 19; 112 static final int QNS_EVENT_EMERGENCY_CALLBACK_MODE_OFF = QNS_EVENT_BASE + 20; 113 static final int QNS_EVENT_WFC_PLATFORM_ENABLED = QNS_EVENT_BASE + 21; 114 static final int QNS_EVENT_WFC_PLATFORM_DISABLED = QNS_EVENT_BASE + 22; 115 static final int QNS_EVENT_SIM_ABSENT = QNS_EVENT_BASE + 23; 116 static final int QNS_EVENT_SIM_LOADED = QNS_EVENT_BASE + 24; 117 static final int QNS_EVENT_WIFI_ENABLED = QNS_EVENT_BASE + 25; 118 static final int QNS_EVENT_TRY_WFC_ACTIVATION = QNS_EVENT_BASE + 100; 119 static final int QNS_EVENT_CANCEL_TRY_WFC_ACTIVATION = QNS_EVENT_BASE + 101; 120 private static final int EVENT_PROVISIONING_INFO_CHANGED = QNS_EVENT_BASE + 200; 121 private static Boolean sIsAirplaneModeOn; 122 private static int sWiFiState = WifiManager.WIFI_STATE_UNKNOWN; 123 private final String mLogTag; 124 private final Context mContext; 125 private final int mSlotIndex; 126 SparseArray<Set<Handler>> mEventHandlers = new SparseArray<>(); 127 private int mSubId; 128 private Uri mCrossSimCallingUri; 129 private Uri mWfcEnabledUri; 130 private Uri mWfcModeUri; 131 private Uri mWfcRoamingEnabledUri; 132 private Uri mWfcRoamingModeUri; 133 @VisibleForTesting UserSettingObserver mUserSettingObserver; 134 private HandlerThread mUserSettingHandlerThread; 135 boolean mLastWfcEnabledByPlatform = false; 136 boolean mLastCrossSimCallingEnabled = false; 137 boolean mLastWfcEnabled = false; 138 int mLastWfcMode = WIFI_MODE_CELLULAR_PREFERRED; 139 boolean mLastWfcRoamingEnabled = false; 140 int mLastWfcModeRoaming = WIFI_MODE_WIFI_PREFERRED; 141 protected final QnsProvisioningListener mQnsProvisioningListener; 142 protected final QnsImsManager mQnsImsManager; 143 private QnsProvisioningListener.QnsProvisioningInfo mLastProvisioningInfo; 144 @VisibleForTesting final QnsEventDispatcherHandler mQnsEventDispatcherHandler; 145 146 @VisibleForTesting 147 final BroadcastReceiver mIntentReceiver = 148 new BroadcastReceiver() { 149 @Override 150 public void onReceive(Context context, Intent intent) { 151 String action = intent.getAction(); 152 int event; 153 Log.d(mLogTag, "onReceive: " + action); 154 switch (action) { 155 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED: 156 int slotId = 157 intent.getIntExtra( 158 CarrierConfigManager.EXTRA_SLOT_INDEX, 159 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 160 int carrierId = 161 intent.getIntExtra( 162 TelephonyManager.EXTRA_CARRIER_ID, 163 TelephonyManager.UNKNOWN_CARRIER_ID); 164 165 onCarrierConfigChanged(context, slotId, carrierId); 166 break; 167 168 case TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED: 169 case TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED: 170 slotId = 171 intent.getIntExtra( 172 CarrierConfigManager.EXTRA_SLOT_INDEX, 173 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 174 int simState = 175 intent.getIntExtra( 176 TelephonyManager.EXTRA_SIM_STATE, 177 TelephonyManager.SIM_STATE_UNKNOWN); 178 onSimStateChanged(slotId, simState); 179 break; 180 181 case Intent.ACTION_AIRPLANE_MODE_CHANGED: 182 Boolean isAirplaneModeOn = intent.getBooleanExtra("state", false); 183 if (sIsAirplaneModeOn != null 184 && sIsAirplaneModeOn.equals(isAirplaneModeOn)) { 185 // no change in apm state 186 break; 187 } 188 sIsAirplaneModeOn = isAirplaneModeOn; 189 event = 190 sIsAirplaneModeOn 191 ? QNS_EVENT_APM_ENABLED 192 : QNS_EVENT_APM_DISABLED; 193 updateHandlers(event); 194 break; 195 196 case WifiManager.WIFI_STATE_CHANGED_ACTION: 197 int wifiState = 198 intent.getIntExtra( 199 WifiManager.EXTRA_WIFI_STATE, 200 WifiManager.WIFI_STATE_UNKNOWN); 201 if (wifiState != sWiFiState) { 202 sWiFiState = wifiState; 203 if (wifiState == WifiManager.WIFI_STATE_DISABLING) { 204 event = QNS_EVENT_WIFI_DISABLING; 205 } else if (wifiState == WifiManager.WIFI_STATE_ENABLED) { 206 event = QNS_EVENT_WIFI_ENABLED; 207 } else { 208 break; 209 } 210 updateHandlers(event); 211 } 212 break; 213 214 case TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED: 215 boolean emergencyMode = 216 intent.getBooleanExtra( 217 TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false); 218 event = 219 emergencyMode 220 ? QNS_EVENT_EMERGENCY_CALLBACK_MODE_ON 221 : QNS_EVENT_EMERGENCY_CALLBACK_MODE_OFF; 222 int slotIndex = intent.getIntExtra(EXTRA_SLOT_INDEX, 0); 223 // getInstance(mContext, slotIndex). 224 if (mSlotIndex == slotIndex) { 225 updateHandlers(event); 226 } 227 break; 228 } 229 } 230 }; 231 232 final BroadcastReceiver mWfcActivationIntentReceiver = 233 new BroadcastReceiver() { 234 @Override 235 public void onReceive(Context context, Intent intent) { 236 String action = intent.getAction(); 237 int event; 238 Log.d(mLogTag, "mWfcActivationIntentReceiver onReceive: " + action); 239 switch (action) { 240 case ACTION_TRY_WFC_CONNECTION: 241 int subId = intent.getIntExtra(EXTRA_SUB_ID, -1); 242 if (subId != mSubId) { 243 Log.d(mLogTag, "Intent subId: " + subId + ", mSubId: " + mSubId); 244 break; 245 } 246 int request = intent.getIntExtra(EXTRA_TRY_STATUS, 0); 247 event = 248 request == STATUS_START 249 ? QNS_EVENT_TRY_WFC_ACTIVATION 250 : QNS_EVENT_CANCEL_TRY_WFC_ACTIVATION; 251 updateHandlers(event); 252 break; 253 } 254 } 255 }; 256 257 /** QnsEventDispatcher constructor */ QnsEventDispatcher( Context context, QnsProvisioningListener provisioningListener, QnsImsManager imsManager, int slotIndex)258 QnsEventDispatcher( 259 Context context, 260 QnsProvisioningListener provisioningListener, 261 QnsImsManager imsManager, 262 int slotIndex) { 263 mContext = context; 264 mSlotIndex = slotIndex; 265 mLogTag = QnsEventDispatcher.class.getSimpleName() + "[" + mSlotIndex + "]"; 266 mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 267 mQnsProvisioningListener = provisioningListener; 268 mQnsImsManager = imsManager; 269 final ContentResolver cr = mContext.getContentResolver(); 270 int airplaneMode = Settings.Global.getInt(cr, Settings.Global.AIRPLANE_MODE_ON, 0); 271 sIsAirplaneModeOn = (airplaneMode == 1); 272 IntentFilter intentFilter = new IntentFilter(); 273 intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 274 intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 275 intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); 276 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 277 intentFilter.addAction(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED); 278 intentFilter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED); 279 mContext.registerReceiver(mIntentReceiver, intentFilter); 280 281 IntentFilter wfcIntentFilter = new IntentFilter(); 282 wfcIntentFilter.addAction(ACTION_TRY_WFC_CONNECTION); 283 mContext.registerReceiver( 284 mWfcActivationIntentReceiver, wfcIntentFilter, Context.RECEIVER_NOT_EXPORTED); 285 286 HandlerThread handlerThread = new HandlerThread(mLogTag); 287 handlerThread.start(); 288 mQnsEventDispatcherHandler = new QnsEventDispatcherHandler(handlerThread.getLooper()); 289 mQnsEventDispatcherHandler.post(() -> loadAndNotifyWfcSettings(mContext, mSlotIndex)); 290 291 mLastProvisioningInfo = new QnsProvisioningListener.QnsProvisioningInfo(); 292 mQnsProvisioningListener.registerProvisioningItemInfoChanged( 293 mQnsEventDispatcherHandler, EVENT_PROVISIONING_INFO_CHANGED, null, true); 294 } 295 loadAndNotifyWfcSettings(Context context, int slotIndex)296 private synchronized void loadAndNotifyWfcSettings(Context context, int slotIndex) { 297 int subId = QnsUtils.getSubId(context, slotIndex); 298 Log.d(mLogTag, "loadAndNotifyWfcSettings for sub:" + subId); 299 if (subId != mSubId) { 300 unregisterContentObserver(); 301 mSubId = subId; 302 registerContentObserver(); 303 } 304 notifyWfcEnabledByPlatform(); 305 notifyCurrentSetting(mCrossSimCallingUri, true); 306 notifyCurrentSetting(mWfcEnabledUri, true); 307 notifyCurrentSetting(mWfcModeUri, true); 308 notifyCurrentSetting(mWfcRoamingEnabledUri, true); 309 notifyCurrentSetting(mWfcRoamingModeUri, true); 310 } 311 onCarrierConfigChanged(Context context, int slotId, int carrierId)312 private synchronized void onCarrierConfigChanged(Context context, int slotId, int carrierId) { 313 if (slotId != mSlotIndex) { 314 return; 315 } 316 317 Log.d(mLogTag, "onCarrierConfigChanged"); 318 loadAndNotifyWfcSettings(context, slotId); 319 320 int event; 321 if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { 322 event = QNS_EVENT_CARRIER_CONFIG_CHANGED; 323 } else { 324 event = QNS_EVENT_CARRIER_CONFIG_UNKNOWN_CARRIER; 325 } 326 327 updateHandlers(event); 328 } 329 registerEvent(List<Integer> events, Handler handler)330 synchronized void registerEvent(List<Integer> events, Handler handler) { 331 for (@QnsEventType int event : events) { 332 if (mEventHandlers.contains(event)) { 333 mEventHandlers.get(event).add(handler); 334 } else { 335 Set<Handler> handlers = new HashSet<>(); 336 handlers.add(handler); 337 mEventHandlers.append(event, handlers); 338 } 339 } 340 notifyImmediately(events, handler); 341 } 342 onSimStateChanged(int slotId, int simState)343 private void onSimStateChanged(int slotId, int simState) { 344 if (slotId != mSlotIndex) { 345 return; 346 } 347 if (simState == TelephonyManager.SIM_STATE_ABSENT) { 348 updateHandlers(QNS_EVENT_SIM_ABSENT); 349 } else if (simState == TelephonyManager.SIM_STATE_LOADED) { 350 updateHandlers(QNS_EVENT_SIM_LOADED); 351 } 352 } 353 notifyImmediately(List<Integer> events, Handler handler)354 private synchronized void notifyImmediately(List<Integer> events, Handler handler) { 355 boolean bWfcPlatformSetting = false; 356 boolean bWfcSetting = false; 357 boolean bWfcModeSetting = false; 358 boolean bWfcRoamingSetting = false; 359 boolean bWfcRoamingModeSetting = false; 360 boolean bCrossSimSetting = false; 361 for (@QnsEventType int event : events) { 362 switch (event) { 363 case QNS_EVENT_WFC_PLATFORM_ENABLED: 364 case QNS_EVENT_WFC_PLATFORM_DISABLED: 365 bWfcPlatformSetting = true; 366 break; 367 case QNS_EVENT_WFC_ENABLED: 368 case QNS_EVENT_WFC_DISABLED: 369 bWfcSetting = true; 370 break; 371 case QNS_EVENT_WFC_ROAMING_ENABLED: 372 case QNS_EVENT_WFC_ROAMING_DISABLED: 373 bWfcRoamingSetting = true; 374 break; 375 case QNS_EVENT_WFC_MODE_TO_WIFI_ONLY: 376 case QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED: 377 case QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED: 378 bWfcModeSetting = true; 379 break; 380 case QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY: 381 case QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED: 382 case QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED: 383 bWfcRoamingModeSetting = true; 384 break; 385 case QnsEventDispatcher.QNS_EVENT_CROSS_SIM_CALLING_ENABLED: 386 case QnsEventDispatcher.QNS_EVENT_CROSS_SIM_CALLING_DISABLED: 387 bCrossSimSetting = true; 388 break; 389 } 390 } 391 392 if (bWfcPlatformSetting) { 393 if (mLastWfcEnabledByPlatform) { 394 updateHandler(handler, QNS_EVENT_WFC_PLATFORM_ENABLED); 395 } else { 396 updateHandler(handler, QNS_EVENT_WFC_PLATFORM_DISABLED); 397 } 398 // checks again whether setting is changed. 399 notifyWfcEnabledByPlatform(); 400 } 401 if (bWfcSetting) { 402 if (mLastWfcEnabled) { 403 updateHandler(handler, QNS_EVENT_WFC_ENABLED); 404 } else { 405 updateHandler(handler, QNS_EVENT_WFC_DISABLED); 406 } 407 // checks again whether setting is changed. 408 notifyCurrentSetting(mWfcEnabledUri, false); 409 } 410 if (bWfcModeSetting) { 411 switch (mLastWfcMode) { 412 case WIFI_MODE_WIFI_ONLY: 413 updateHandler(handler, QNS_EVENT_WFC_MODE_TO_WIFI_ONLY); 414 break; 415 case WIFI_MODE_CELLULAR_PREFERRED: 416 updateHandler(handler, QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED); 417 break; 418 case WIFI_MODE_WIFI_PREFERRED: 419 updateHandler(handler, QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED); 420 break; 421 } 422 // checks again whether setting is changed. 423 notifyCurrentSetting(mWfcModeUri, false); 424 } 425 if (bWfcRoamingSetting) { 426 if (mLastWfcRoamingEnabled) { 427 updateHandler(handler, QNS_EVENT_WFC_ROAMING_ENABLED); 428 } else { 429 updateHandler(handler, QNS_EVENT_WFC_ROAMING_DISABLED); 430 } 431 // checks again whether setting is changed. 432 notifyCurrentSetting(mWfcRoamingEnabledUri, false); 433 } 434 if (bWfcRoamingModeSetting) { 435 switch (mLastWfcModeRoaming) { 436 case WIFI_MODE_WIFI_ONLY: 437 updateHandler(handler, QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY); 438 break; 439 case WIFI_MODE_CELLULAR_PREFERRED: 440 updateHandler(handler, QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED); 441 break; 442 case WIFI_MODE_WIFI_PREFERRED: 443 updateHandler(handler, QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED); 444 break; 445 } 446 // checks again whether setting is changed. 447 notifyCurrentSetting(mWfcRoamingModeUri, false); 448 } 449 if (bCrossSimSetting) { 450 if (mLastCrossSimCallingEnabled) { 451 updateHandler(handler, QNS_EVENT_CROSS_SIM_CALLING_ENABLED); 452 } else { 453 updateHandler(handler, QNS_EVENT_CROSS_SIM_CALLING_DISABLED); 454 } 455 // checks again whether setting is changed. 456 notifyCurrentSetting(mCrossSimCallingUri, false); 457 } 458 } 459 unregisterEvent(Handler handler)460 synchronized void unregisterEvent(Handler handler) { 461 for (int i = 0; i < mEventHandlers.size(); i++) { 462 Set<Handler> handlers = mEventHandlers.valueAt(i); 463 handlers.remove(handler); 464 if (handlers.isEmpty()) { 465 mEventHandlers.delete(mEventHandlers.keyAt(i)); 466 i--; 467 } 468 } 469 if (mEventHandlers.size() == 0) { 470 close(); 471 } 472 } 473 close()474 public void close() { 475 try { 476 mContext.unregisterReceiver(mIntentReceiver); 477 } catch (IllegalArgumentException ignored) { 478 } 479 if (mUserSettingObserver != null) { 480 mContext.getContentResolver().unregisterContentObserver(mUserSettingObserver); 481 } 482 if (mUserSettingHandlerThread != null) { 483 mUserSettingHandlerThread.quit(); 484 } 485 if (mQnsProvisioningListener != null) { 486 mQnsProvisioningListener.unregisterProvisioningItemInfoChanged( 487 mQnsEventDispatcherHandler); 488 } 489 } 490 unregisterContentObserver()491 private synchronized void unregisterContentObserver() { 492 if (mUserSettingObserver != null) { 493 mContext.getContentResolver().unregisterContentObserver(mUserSettingObserver); 494 } 495 mCrossSimCallingUri = null; 496 mWfcEnabledUri = null; 497 mWfcModeUri = null; 498 mWfcRoamingEnabledUri = null; 499 mWfcRoamingModeUri = null; 500 } 501 registerContentObserver()502 private void registerContentObserver() { 503 // Register for content observer 504 if (mUserSettingObserver == null) { 505 Log.d(mLogTag, "create mUserSettingObserver"); 506 mUserSettingHandlerThread = new HandlerThread(QnsEventDispatcher.class.getSimpleName()); 507 mUserSettingHandlerThread.start(); 508 Looper looper = mUserSettingHandlerThread.getLooper(); 509 Handler handler = new Handler(looper); 510 mUserSettingObserver = new UserSettingObserver(handler); 511 512 // init 513 mLastWfcEnabledByPlatform = QnsUtils.isWfcEnabledByPlatform(mQnsImsManager); 514 mLastCrossSimCallingEnabled = QnsUtils.isCrossSimCallingEnabled(mQnsImsManager); 515 mLastWfcEnabled = 516 QnsUtils.isWfcEnabled(mQnsImsManager, mQnsProvisioningListener, false); 517 mLastWfcMode = QnsUtils.getWfcMode(mQnsImsManager, false); 518 mLastWfcRoamingEnabled = 519 QnsUtils.isWfcEnabled(mQnsImsManager, mQnsProvisioningListener, true); 520 mLastWfcModeRoaming = QnsUtils.getWfcMode(mQnsImsManager, true); 521 } 522 523 if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 524 return; 525 } 526 527 StringBuilder sb = new StringBuilder("registerContentObserver"); 528 sb.append(" subId:").append(mSubId); 529 ContentResolver resolver = mContext.getContentResolver(); 530 531 // Update current Cross Sim Calling setting 532 Uri crossSimCallingUri = getUri(SubscriptionManager.CROSS_SIM_ENABLED_CONTENT_URI, mSubId); 533 if (!crossSimCallingUri.equals(mCrossSimCallingUri)) { 534 mCrossSimCallingUri = crossSimCallingUri; 535 sb.append(" crossSimCallingUri/").append(mSubId); 536 resolver.registerContentObserver(mCrossSimCallingUri, true, mUserSettingObserver); 537 } 538 539 // Update current Wi-Fi Calling setting 540 Uri wfcEnabledUri = getUri(SubscriptionManager.WFC_ENABLED_CONTENT_URI, mSubId); 541 if (!wfcEnabledUri.equals(mWfcEnabledUri)) { 542 mWfcEnabledUri = wfcEnabledUri; 543 sb.append(" wfcEnabledUri/").append(mSubId); 544 resolver.registerContentObserver(mWfcEnabledUri, true, mUserSettingObserver); 545 } 546 547 // Update current Wi-Fi Calling Mode setting 548 Uri wfcModeUri = getUri(SubscriptionManager.WFC_MODE_CONTENT_URI, mSubId); 549 if (!wfcModeUri.equals(mWfcModeUri)) { 550 mWfcModeUri = wfcModeUri; 551 sb.append(" wfcModeUri/").append(mSubId); 552 resolver.registerContentObserver(mWfcModeUri, true, mUserSettingObserver); 553 } 554 555 // Update current Wi-Fi Calling setting for roaming 556 Uri wfcRoamEnabledUri = getUri(SubscriptionManager.WFC_ROAMING_ENABLED_CONTENT_URI, mSubId); 557 if (!wfcRoamEnabledUri.equals(mWfcRoamingEnabledUri)) { 558 mWfcRoamingEnabledUri = wfcRoamEnabledUri; 559 sb.append(" wfcRoamEnabledUri/").append(mSubId); 560 resolver.registerContentObserver(mWfcRoamingEnabledUri, true, mUserSettingObserver); 561 } 562 563 // Update current Wi-Fi Calling Mode setting for roaming 564 Uri wfcRoamingModeUri = getUri(SubscriptionManager.WFC_ROAMING_MODE_CONTENT_URI, mSubId); 565 if (!wfcRoamingModeUri.equals(mWfcRoamingModeUri)) { 566 mWfcRoamingModeUri = wfcRoamingModeUri; 567 sb.append(" wfcRoamingModeUri/").append(mSubId); 568 resolver.registerContentObserver(mWfcRoamingModeUri, true, mUserSettingObserver); 569 } 570 571 Log.d(mLogTag, sb.toString()); 572 } 573 getUri(Uri uri, int subId)574 private Uri getUri(Uri uri, int subId) { 575 return Uri.withAppendedPath(uri, String.valueOf(subId)); 576 } 577 notifyCurrentSetting(Uri uri, boolean bForceUpdate)578 void notifyCurrentSetting(Uri uri, boolean bForceUpdate) { 579 if (uri == null) { 580 return; 581 } 582 try { 583 String uriString = uri.getPath(); 584 int subIndex = Integer.parseInt(uriString.substring(uriString.lastIndexOf('/') + 1)); 585 int slotIndex = SubscriptionManager.getSlotIndex(subIndex); 586 int event = QNS_EVENT_BASE; 587 588 if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { 589 Log.e(mLogTag, "Invalid slot index: " + slotIndex); 590 return; 591 } 592 593 StringBuilder sb = new StringBuilder("notifyCurrentSetting"); 594 sb.append(", bForceUpdate:").append(bForceUpdate); 595 596 Log.d(mLogTag, "CrossSimCallingUri:" + mCrossSimCallingUri); 597 Log.d(mLogTag, "mWfcEnabledUri:" + mWfcEnabledUri); 598 Log.d(mLogTag, "mWfcModeUri:" + mWfcModeUri); 599 Log.d(mLogTag, "mWfcRoamingEnabledUri:" + mWfcRoamingEnabledUri); 600 Log.d(mLogTag, "mWfcRoamingModeUri:" + mWfcRoamingModeUri); 601 602 if (uri.equals(mCrossSimCallingUri)) { 603 boolean isCrossSimCallingEnabled = 604 QnsUtils.isCrossSimCallingEnabled(mQnsImsManager); 605 if (mLastCrossSimCallingEnabled != isCrossSimCallingEnabled || bForceUpdate) { 606 if (isCrossSimCallingEnabled) { 607 event = QNS_EVENT_CROSS_SIM_CALLING_ENABLED; 608 } else { 609 event = QNS_EVENT_CROSS_SIM_CALLING_DISABLED; 610 } 611 mLastCrossSimCallingEnabled = isCrossSimCallingEnabled; 612 sb.append(", isCrossSimCallingEnabled:").append(isCrossSimCallingEnabled); 613 Log.d(mLogTag, sb.toString()); 614 updateHandlers(event); 615 } 616 } else if (uri.equals(mWfcEnabledUri)) { 617 boolean isWfcEnabled = 618 QnsUtils.isWfcEnabled(mQnsImsManager, mQnsProvisioningListener, false); 619 if (mLastWfcEnabled != isWfcEnabled || bForceUpdate) { 620 if (isWfcEnabled) { 621 event = QNS_EVENT_WFC_ENABLED; 622 } else { 623 event = QNS_EVENT_WFC_DISABLED; 624 } 625 mLastWfcEnabled = isWfcEnabled; 626 sb.append(", isWfcEnabled:").append(isWfcEnabled); 627 Log.d(mLogTag, sb.toString()); 628 updateHandlers(event); 629 } 630 } else if (uri.equals(mWfcModeUri)) { 631 int wfcMode = QnsUtils.getWfcMode(mQnsImsManager, false); 632 if (mLastWfcMode != wfcMode || bForceUpdate) { 633 switch (wfcMode) { 634 case WIFI_MODE_WIFI_ONLY: 635 event = QNS_EVENT_WFC_MODE_TO_WIFI_ONLY; 636 break; 637 case WIFI_MODE_CELLULAR_PREFERRED: 638 event = QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED; 639 break; 640 case WIFI_MODE_WIFI_PREFERRED: 641 event = QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED; 642 break; 643 } 644 mLastWfcMode = wfcMode; 645 sb.append(", wfcMode:").append(wfcMode); 646 Log.d(mLogTag, sb.toString()); 647 updateHandlers(event); 648 } 649 } else if (uri.equals(mWfcRoamingEnabledUri)) { 650 boolean isWfcRoamingEnabled = 651 QnsUtils.isWfcEnabled(mQnsImsManager, mQnsProvisioningListener, true); 652 if (mLastWfcRoamingEnabled != isWfcRoamingEnabled || bForceUpdate) { 653 if (isWfcRoamingEnabled) { 654 event = QNS_EVENT_WFC_ROAMING_ENABLED; 655 } else { 656 event = QNS_EVENT_WFC_ROAMING_DISABLED; 657 } 658 mLastWfcRoamingEnabled = isWfcRoamingEnabled; 659 sb.append(", isWfcRoamingEnabled:").append(isWfcRoamingEnabled); 660 Log.d(mLogTag, sb.toString()); 661 updateHandlers(event); 662 } 663 } else if (uri.equals(mWfcRoamingModeUri)) { 664 int wfcModeRoaming = QnsUtils.getWfcMode(mQnsImsManager, true); 665 if (mLastWfcModeRoaming != wfcModeRoaming || bForceUpdate) { 666 switch (wfcModeRoaming) { 667 case WIFI_MODE_WIFI_ONLY: 668 event = QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY; 669 break; 670 case WIFI_MODE_CELLULAR_PREFERRED: 671 event = QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED; 672 break; 673 case WIFI_MODE_WIFI_PREFERRED: 674 event = QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED; 675 break; 676 } 677 mLastWfcModeRoaming = wfcModeRoaming; 678 sb.append(", wfcModeRoaming:").append(wfcModeRoaming); 679 Log.d(mLogTag, sb.toString()); 680 updateHandlers(event); 681 } 682 } else { 683 Log.e(mLogTag, "Unknown Uri : " + uri); 684 } 685 } catch (Exception e) { 686 Log.e(mLogTag, "notifyCurrentSetting got exception:" + e); 687 e.printStackTrace(); 688 } 689 } 690 notifyWfcEnabledByPlatform()691 void notifyWfcEnabledByPlatform() { 692 boolean isWfcEnabledByPlatform = QnsUtils.isWfcEnabledByPlatform(mQnsImsManager); 693 if (mLastWfcEnabledByPlatform != isWfcEnabledByPlatform) { 694 mLastWfcEnabledByPlatform = isWfcEnabledByPlatform; 695 Log.d(mLogTag, "notifyWfcEnabledByPlatform:" + isWfcEnabledByPlatform); 696 if (isWfcEnabledByPlatform) { 697 updateHandlers(QNS_EVENT_WFC_PLATFORM_ENABLED); 698 } else { 699 updateHandlers(QNS_EVENT_WFC_PLATFORM_DISABLED); 700 } 701 } 702 } 703 updateHandler(Handler handler, int event)704 private synchronized void updateHandler(Handler handler, int event) { 705 try { 706 if (mEventHandlers.get(event).contains(handler)) { 707 Log.d(mLogTag, "Updating handler for the event: " + event); 708 handler.obtainMessage(event).sendToTarget(); 709 } 710 } catch (Exception e) { 711 Log.e(mLogTag, "updateHandler got exception e:" + e); 712 } 713 } 714 updateHandlers(int event)715 private synchronized void updateHandlers(int event) { 716 if (mEventHandlers.contains(event)) { 717 Log.d(mLogTag, "Updating handlers for the event: " + event); 718 for (Handler handler : mEventHandlers.get(event)) { 719 handler.obtainMessage(event).sendToTarget(); 720 } 721 } 722 } 723 724 @VisibleForTesting 725 class UserSettingObserver extends ContentObserver { UserSettingObserver(Handler h)726 UserSettingObserver(Handler h) { 727 super(h); 728 } 729 730 @Override onChange(boolean selfChange, Uri uri)731 public void onChange(boolean selfChange, Uri uri) { 732 Log.d(mLogTag, "onUserSettingChanged"); 733 onUserSettingChanged(uri); 734 } 735 } 736 onUserSettingChanged(Uri uri)737 private synchronized void onUserSettingChanged(Uri uri) { 738 if (mCrossSimCallingUri.equals(uri)) { 739 notifyCurrentSetting(uri, false); 740 } else if (mWfcEnabledUri.equals(uri)) { 741 // checks platform changes first. 742 notifyWfcEnabledByPlatform(); 743 744 notifyCurrentSetting(uri, false); 745 } else if (mWfcModeUri.equals(uri)) { 746 notifyCurrentSetting(uri, false); 747 } else if (mWfcRoamingEnabledUri.equals(uri)) { 748 // checks platform changes first. 749 notifyWfcEnabledByPlatform(); 750 751 notifyCurrentSetting(uri, false); 752 } else if (mWfcRoamingModeUri.equals(uri)) { 753 notifyCurrentSetting(uri, false); 754 } 755 } 756 757 private class QnsEventDispatcherHandler extends Handler { 758 /** 759 * Use the provided {@link Looper} instead of the default one. 760 * 761 * @param looper The looper, must not be null. 762 */ QnsEventDispatcherHandler(Looper looper)763 QnsEventDispatcherHandler(Looper looper) { 764 super(looper); 765 } 766 767 @Override handleMessage(Message message)768 public void handleMessage(Message message) { 769 Log.d(mLogTag, "handleMessage msg=" + message.what); 770 QnsAsyncResult ar = (QnsAsyncResult) message.obj; 771 switch (message.what) { 772 case EVENT_PROVISIONING_INFO_CHANGED: 773 onProvisioningInfoChanged( 774 (QnsProvisioningListener.QnsProvisioningInfo) ar.mResult); 775 break; 776 default: 777 break; 778 } 779 } 780 } 781 onProvisioningInfoChanged( QnsProvisioningListener.QnsProvisioningInfo info)782 private synchronized void onProvisioningInfoChanged( 783 QnsProvisioningListener.QnsProvisioningInfo info) { 784 785 Log.d(mLogTag, "onProvisioningInfoChanged info:" + info); 786 787 if (!info.equalsIntegerItem( 788 mLastProvisioningInfo, 789 ProvisioningManager.KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE)) { 790 Log.d( 791 mLogTag, 792 "onProvisioningInfoChanged, KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE(" 793 + ProvisioningManager.KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE 794 + ") is provisioned to " 795 + info.getIntegerItem( 796 ProvisioningManager 797 .KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE)); 798 // checks platform changes first. 799 notifyWfcEnabledByPlatform(); 800 notifyCurrentSetting(mWfcRoamingEnabledUri, false); 801 } 802 if (!info.equalsIntegerItem( 803 mLastProvisioningInfo, ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE)) { 804 Log.d( 805 mLogTag, 806 "onProvisioningInfoChanged, KEY_VOICE_OVER_WIFI_MODE_OVERRIDE(" 807 + ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE 808 + ") is provisioned to " 809 + info.getIntegerItem( 810 ProvisioningManager.KEY_VOICE_OVER_WIFI_MODE_OVERRIDE)); 811 notifyCurrentSetting(mWfcModeUri, false); 812 } 813 if (!info.equalsIntegerItem( 814 mLastProvisioningInfo, ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE)) { 815 Log.d( 816 mLogTag, 817 "onProvisioningInfoChanged, KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE(" 818 + ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE 819 + ") is provisioned to " 820 + info.getIntegerItem( 821 ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE)); 822 // checks platform changes first. 823 notifyWfcEnabledByPlatform(); 824 notifyCurrentSetting(mWfcEnabledUri, false); 825 } 826 827 mLastProvisioningInfo = info; 828 } 829 isAirplaneModeToggleOn()830 boolean isAirplaneModeToggleOn() { 831 return sIsAirplaneModeOn; 832 } 833 } 834