1 /* 2 * Copyright 2020 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.phone; 18 19 import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML; 20 import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED; 21 import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION; 22 23 import android.Manifest; 24 import android.app.role.OnRoleHoldersChangedListener; 25 import android.app.role.RoleManager; 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.pm.PackageManager; 31 import android.os.Build; 32 import android.os.Handler; 33 import android.os.HandlerThread; 34 import android.os.Looper; 35 import android.os.Message; 36 import android.os.PersistableBundle; 37 import android.os.RemoteException; 38 import android.os.UserHandle; 39 import android.telephony.CarrierConfigManager; 40 import android.telephony.SubscriptionManager; 41 import android.telephony.TelephonyRegistryManager; 42 import android.telephony.ims.ProvisioningManager; 43 import android.telephony.ims.RcsConfig; 44 import android.telephony.ims.aidl.IImsConfig; 45 import android.telephony.ims.aidl.IRcsConfigCallback; 46 import android.text.TextUtils; 47 import android.util.ArraySet; 48 import android.util.SparseArray; 49 50 import com.android.ims.FeatureConnector; 51 import com.android.ims.FeatureUpdates; 52 import com.android.ims.RcsFeatureManager; 53 import com.android.internal.annotations.VisibleForTesting; 54 import com.android.internal.telephony.metrics.RcsStats; 55 import com.android.internal.telephony.metrics.RcsStats.RcsProvisioningCallback; 56 import com.android.internal.telephony.util.HandlerExecutor; 57 import com.android.internal.util.CollectionUtils; 58 import com.android.telephony.Rlog; 59 60 import java.util.Arrays; 61 import java.util.HashMap; 62 import java.util.Iterator; 63 import java.util.List; 64 import java.util.concurrent.ConcurrentHashMap; 65 import java.util.concurrent.Executor; 66 67 /** 68 * Class to monitor RCS Provisioning Status 69 */ 70 public class RcsProvisioningMonitor { 71 private static final String TAG = "RcsProvisioningMonitor"; 72 private static final boolean DBG = Build.IS_ENG; 73 74 private static final int EVENT_SUB_CHANGED = 1; 75 private static final int EVENT_DMA_CHANGED = 2; 76 private static final int EVENT_CC_CHANGED = 3; 77 private static final int EVENT_CONFIG_RECEIVED = 4; 78 private static final int EVENT_RECONFIG_REQUEST = 5; 79 private static final int EVENT_DEVICE_CONFIG_OVERRIDE = 6; 80 private static final int EVENT_CARRIER_CONFIG_OVERRIDE = 7; 81 private static final int EVENT_RESET = 8; 82 private static final int EVENT_FEATURE_ENABLED_OVERRIDE = 9; 83 84 // indicate that the carrier single registration capable is initial value as 85 // carrier config is not ready yet. 86 private static final int MASK_CAP_CARRIER_INIT = 0xF000; 87 88 private final PhoneGlobals mPhone; 89 private final Handler mHandler; 90 // Cache the RCS provsioning info and related sub id 91 private final ConcurrentHashMap<Integer, RcsProvisioningInfo> mRcsProvisioningInfos = 92 new ConcurrentHashMap<>(); 93 private Boolean mDeviceSingleRegistrationEnabledOverride; 94 private final HashMap<Integer, Boolean> mCarrierSingleRegistrationEnabledOverride = 95 new HashMap<>(); 96 private final ConcurrentHashMap<Integer, Boolean> mImsFeatureValidationOverride = 97 new ConcurrentHashMap<>(); 98 private String mDmaPackageName; 99 private final SparseArray<RcsFeatureListener> mRcsFeatureListeners = new SparseArray<>(); 100 private volatile boolean mTestModeEnabled; 101 102 private final CarrierConfigManager mCarrierConfigManager; 103 private final DmaChangedListener mDmaChangedListener; 104 private final SubscriptionManager mSubscriptionManager; 105 private final TelephonyRegistryManager mTelephonyRegistryManager; 106 private final RoleManagerAdapter mRoleManager; 107 private FeatureConnectorFactory<RcsFeatureManager> mFeatureFactory; 108 109 private RcsStats mRcsStats; 110 111 private static RcsProvisioningMonitor sInstance; 112 113 private final SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener = 114 new SubscriptionManager.OnSubscriptionsChangedListener() { 115 @Override 116 public void onSubscriptionsChanged() { 117 if (!mHandler.hasMessages(EVENT_SUB_CHANGED)) { 118 mHandler.sendEmptyMessage(EVENT_SUB_CHANGED); 119 } 120 } 121 }; 122 123 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 124 @Override 125 public void onReceive(Context context, Intent intent) { 126 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals( 127 intent.getAction())) { 128 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 129 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 130 logv("Carrier-config changed for sub : " + subId); 131 if (SubscriptionManager.isValidSubscriptionId(subId) 132 && !mHandler.hasMessages(EVENT_CC_CHANGED)) { 133 mHandler.sendEmptyMessage(EVENT_CC_CHANGED); 134 } 135 } 136 } 137 }; 138 139 private final class DmaChangedListener implements OnRoleHoldersChangedListener { 140 @Override onRoleHoldersChanged(String role, UserHandle user)141 public void onRoleHoldersChanged(String role, UserHandle user) { 142 if (RoleManager.ROLE_SMS.equals(role)) { 143 logv("default messaging application changed."); 144 mHandler.sendEmptyMessage(EVENT_DMA_CHANGED); 145 } 146 } 147 register()148 public void register() { 149 try { 150 mRoleManager.addOnRoleHoldersChangedListenerAsUser( 151 mPhone.getMainExecutor(), this, UserHandle.SYSTEM); 152 } catch (RuntimeException e) { 153 loge("Could not register dma change listener due to " + e); 154 } 155 } 156 unregister()157 public void unregister() { 158 try { 159 mRoleManager.removeOnRoleHoldersChangedListenerAsUser(this, UserHandle.SYSTEM); 160 } catch (RuntimeException e) { 161 loge("Could not unregister dma change listener due to " + e); 162 } 163 } 164 } 165 166 private final class MyHandler extends Handler { MyHandler(Looper looper)167 MyHandler(Looper looper) { 168 super(looper); 169 } 170 171 @Override handleMessage(Message msg)172 public void handleMessage(Message msg) { 173 logv("handleMessage: " + msg); 174 switch (msg.what) { 175 case EVENT_SUB_CHANGED: 176 onSubChanged(); 177 break; 178 case EVENT_DMA_CHANGED: 179 onDefaultMessagingApplicationChanged(); 180 break; 181 case EVENT_CC_CHANGED: 182 onCarrierConfigChange(); 183 break; 184 case EVENT_CONFIG_RECEIVED: 185 onConfigReceived(msg.arg1, (byte[]) msg.obj, msg.arg2 == 1); 186 break; 187 case EVENT_RECONFIG_REQUEST: 188 onReconfigRequest(msg.arg1); 189 break; 190 case EVENT_DEVICE_CONFIG_OVERRIDE: 191 Boolean deviceEnabled = (Boolean) msg.obj; 192 if (!booleanEquals(deviceEnabled, mDeviceSingleRegistrationEnabledOverride)) { 193 mDeviceSingleRegistrationEnabledOverride = deviceEnabled; 194 onCarrierConfigChange(); 195 } 196 break; 197 case EVENT_CARRIER_CONFIG_OVERRIDE: 198 Boolean carrierEnabledOverride = (Boolean) msg.obj; 199 Boolean carrierEnabled = mCarrierSingleRegistrationEnabledOverride.put( 200 msg.arg1, carrierEnabledOverride); 201 if (!booleanEquals(carrierEnabledOverride, carrierEnabled)) { 202 onCarrierConfigChange(); 203 } 204 break; 205 case EVENT_RESET: 206 reset(); 207 break; 208 default: 209 loge("Unhandled event " + msg.what); 210 } 211 } 212 } 213 214 private final class RcsProvisioningInfo { 215 private int mSubId; 216 private volatile int mSingleRegistrationCapability; 217 private volatile byte[] mConfig; 218 private ArraySet<IRcsConfigCallback> mRcsConfigCallbacks; 219 private IImsConfig mIImsConfig; 220 private boolean mHasReconfigRequest; 221 RcsProvisioningInfo(int subId, int singleRegistrationCapability, byte[] config)222 RcsProvisioningInfo(int subId, int singleRegistrationCapability, byte[] config) { 223 mSubId = subId; 224 mSingleRegistrationCapability = singleRegistrationCapability; 225 mConfig = config; 226 mRcsConfigCallbacks = new ArraySet<>(); 227 registerRcsFeatureListener(this); 228 } 229 getSubId()230 int getSubId() { 231 return mSubId; 232 } 233 setSingleRegistrationCapability(int singleRegistrationCapability)234 void setSingleRegistrationCapability(int singleRegistrationCapability) { 235 if (mSingleRegistrationCapability != singleRegistrationCapability) { 236 mSingleRegistrationCapability = singleRegistrationCapability; 237 notifyDma(); 238 239 // update whether single registration supported. 240 mRcsStats.setEnableSingleRegistration(mSubId, 241 mSingleRegistrationCapability == ProvisioningManager.STATUS_CAPABLE); 242 } 243 } 244 notifyDma()245 void notifyDma() { 246 // notify only if capable value has been updated when carrier config ready. 247 if ((mSingleRegistrationCapability & MASK_CAP_CARRIER_INIT) != MASK_CAP_CARRIER_INIT) { 248 logi("notify default messaging app for sub:" + mSubId + " with capability:" 249 + mSingleRegistrationCapability); 250 notifyDmaForSub(mSubId, mSingleRegistrationCapability); 251 } 252 } 253 getSingleRegistrationCapability()254 int getSingleRegistrationCapability() { 255 return mSingleRegistrationCapability; 256 } 257 setConfig(byte[] config)258 void setConfig(byte[] config) { 259 if (!Arrays.equals(mConfig, config)) { 260 mConfig = config; 261 if (mConfig != null) { 262 notifyRcsAutoConfigurationReceived(); 263 } else { 264 notifyRcsAutoConfigurationRemoved(); 265 } 266 } 267 } 268 getConfig()269 byte[] getConfig() { 270 return mConfig; 271 } 272 addRcsConfigCallback(IRcsConfigCallback cb)273 boolean addRcsConfigCallback(IRcsConfigCallback cb) { 274 if (mIImsConfig == null) { 275 logd("fail to addRcsConfigCallback as imsConfig is null"); 276 return false; 277 } 278 279 synchronized (mRcsConfigCallbacks) { 280 try { 281 mIImsConfig.addRcsConfigCallback(cb); 282 } catch (RemoteException e) { 283 loge("fail to addRcsConfigCallback due to " + e); 284 return false; 285 } 286 mRcsConfigCallbacks.add(cb); 287 } 288 return true; 289 } 290 removeRcsConfigCallback(IRcsConfigCallback cb)291 boolean removeRcsConfigCallback(IRcsConfigCallback cb) { 292 boolean result = true; 293 294 synchronized (mRcsConfigCallbacks) { 295 if (mIImsConfig != null) { 296 try { 297 mIImsConfig.removeRcsConfigCallback(cb); 298 } catch (RemoteException e) { 299 loge("fail to removeRcsConfigCallback due to " + e); 300 } 301 } else { 302 // Return false but continue to remove the callback 303 result = false; 304 } 305 306 try { 307 cb.onRemoved(); 308 } catch (RemoteException e) { 309 logd("Failed to notify onRemoved due to dead binder of " + cb); 310 } 311 mRcsConfigCallbacks.remove(cb); 312 } 313 return result; 314 } 315 triggerRcsReconfiguration()316 void triggerRcsReconfiguration() { 317 if (mIImsConfig != null) { 318 try { 319 logv("triggerRcsReconfiguration for sub:" + mSubId); 320 mIImsConfig.triggerRcsReconfiguration(); 321 mHasReconfigRequest = false; 322 } catch (RemoteException e) { 323 loge("triggerRcsReconfiguration failed due to " + e); 324 } 325 } else { 326 logd("triggerRcsReconfiguration failed due to IImsConfig null."); 327 mHasReconfigRequest = true; 328 } 329 } 330 destroy()331 void destroy() { 332 unregisterRcsFeatureListener(this); 333 clear(); 334 mIImsConfig = null; 335 mRcsConfigCallbacks = null; 336 } 337 clear()338 void clear() { 339 setConfig(null); 340 clearCallbacks(); 341 } 342 onRcsStatusChanged(IImsConfig binder)343 void onRcsStatusChanged(IImsConfig binder) { 344 logv("onRcsStatusChanged for sub:" + mSubId + ", IImsConfig?" + binder); 345 if (mIImsConfig != binder) { 346 mIImsConfig = binder; 347 if (mIImsConfig != null) { 348 if (mHasReconfigRequest) { 349 triggerRcsReconfiguration(); 350 } else { 351 notifyRcsAutoConfigurationReceived(); 352 } 353 354 // check callback for metrics if not registered, register callback 355 registerMetricsCallback(); 356 } else { 357 // clear callbacks if rcs disconnected 358 clearCallbacks(); 359 } 360 } 361 } 362 notifyRcsAutoConfigurationReceived()363 private void notifyRcsAutoConfigurationReceived() { 364 if (mConfig == null) { 365 logd("Rcs config is null for sub : " + mSubId); 366 return; 367 } 368 369 if (mIImsConfig != null) { 370 try { 371 logv("notifyRcsAutoConfigurationReceived for sub:" + mSubId); 372 mIImsConfig.notifyRcsAutoConfigurationReceived(mConfig, false); 373 } catch (RemoteException e) { 374 loge("notifyRcsAutoConfigurationReceived failed due to " + e); 375 } 376 } else { 377 logd("notifyRcsAutoConfigurationReceived failed due to IImsConfig null."); 378 } 379 } 380 notifyRcsAutoConfigurationRemoved()381 private void notifyRcsAutoConfigurationRemoved() { 382 if (mIImsConfig != null) { 383 try { 384 logv("notifyRcsAutoConfigurationRemoved for sub:" + mSubId); 385 mIImsConfig.notifyRcsAutoConfigurationRemoved(); 386 } catch (RemoteException e) { 387 loge("notifyRcsAutoConfigurationRemoved failed due to " + e); 388 } 389 } else { 390 logd("notifyRcsAutoConfigurationRemoved failed due to IImsConfig null."); 391 } 392 } 393 clearCallbacks()394 private void clearCallbacks() { 395 synchronized (mRcsConfigCallbacks) { 396 Iterator<IRcsConfigCallback> it = mRcsConfigCallbacks.iterator(); 397 while (it.hasNext()) { 398 IRcsConfigCallback cb = it.next(); 399 if (mIImsConfig != null) { 400 try { 401 mIImsConfig.removeRcsConfigCallback(cb); 402 } catch (RemoteException e) { 403 loge("fail to removeRcsConfigCallback due to " + e); 404 } 405 } 406 try { 407 cb.onRemoved(); 408 } catch (RemoteException e) { 409 logd("Failed to notify onRemoved due to dead binder of " + cb); 410 } 411 it.remove(); 412 } 413 } 414 } 415 registerMetricsCallback()416 private void registerMetricsCallback() { 417 RcsProvisioningCallback rcsProvisioningCallback = mRcsStats.getRcsProvisioningCallback( 418 mSubId, mSingleRegistrationCapability == ProvisioningManager.STATUS_CAPABLE); 419 420 // if not yet registered, register callback and set registered value 421 if (rcsProvisioningCallback != null && !rcsProvisioningCallback.getRegistered()) { 422 if (addRcsConfigCallback(rcsProvisioningCallback)) { 423 rcsProvisioningCallback.setRegistered(true); 424 } 425 } 426 } 427 } 428 429 @VisibleForTesting 430 public interface FeatureConnectorFactory<U extends FeatureUpdates> { 431 /** 432 * @return a {@link FeatureConnector} associated for the given {@link FeatureUpdates} 433 * and slot index. 434 */ create(Context context, int slotIndex, FeatureConnector.Listener<U> listener, Executor executor, String logPrefix)435 FeatureConnector<U> create(Context context, int slotIndex, 436 FeatureConnector.Listener<U> listener, Executor executor, String logPrefix); 437 } 438 439 private final class RcsFeatureListener implements FeatureConnector.Listener<RcsFeatureManager> { 440 private final ArraySet<RcsProvisioningInfo> mRcsProvisioningInfos = new ArraySet<>(); 441 private RcsFeatureManager mRcsFeatureManager; 442 private FeatureConnector<RcsFeatureManager> mConnector; 443 RcsFeatureListener(int slotId)444 RcsFeatureListener(int slotId) { 445 mConnector = mFeatureFactory.create( 446 mPhone, slotId, this, new HandlerExecutor(mHandler), TAG); 447 mConnector.connect(); 448 } 449 destroy()450 void destroy() { 451 mConnector.disconnect(); 452 mConnector = null; 453 mRcsFeatureManager = null; 454 mRcsProvisioningInfos.clear(); 455 } 456 addRcsProvisioningInfo(RcsProvisioningInfo info)457 void addRcsProvisioningInfo(RcsProvisioningInfo info) { 458 if (!mRcsProvisioningInfos.contains(info)) { 459 mRcsProvisioningInfos.add(info); 460 info.onRcsStatusChanged(mRcsFeatureManager == null ? null 461 : mRcsFeatureManager.getConfig()); 462 } 463 } 464 removeRcsProvisioningInfo(RcsProvisioningInfo info)465 void removeRcsProvisioningInfo(RcsProvisioningInfo info) { 466 mRcsProvisioningInfos.remove(info); 467 } 468 469 @Override connectionReady(RcsFeatureManager manager, int subId)470 public void connectionReady(RcsFeatureManager manager, int subId) { 471 mRcsFeatureManager = manager; 472 mRcsProvisioningInfos.forEach(v -> v.onRcsStatusChanged(manager.getConfig())); 473 } 474 475 @Override connectionUnavailable(int reason)476 public void connectionUnavailable(int reason) { 477 mRcsFeatureManager = null; 478 mRcsProvisioningInfos.forEach(v -> v.onRcsStatusChanged(null)); 479 } 480 } 481 482 @VisibleForTesting RcsProvisioningMonitor(PhoneGlobals app, Looper looper, RoleManagerAdapter roleManager, FeatureConnectorFactory<RcsFeatureManager> factory, RcsStats rcsStats)483 public RcsProvisioningMonitor(PhoneGlobals app, Looper looper, RoleManagerAdapter roleManager, 484 FeatureConnectorFactory<RcsFeatureManager> factory, RcsStats rcsStats) { 485 mPhone = app; 486 mHandler = new MyHandler(looper); 487 mCarrierConfigManager = mPhone.getSystemService(CarrierConfigManager.class); 488 mSubscriptionManager = mPhone.getSystemService(SubscriptionManager.class); 489 mTelephonyRegistryManager = mPhone.getSystemService(TelephonyRegistryManager.class); 490 mRoleManager = roleManager; 491 mDmaPackageName = getDmaPackageName(); 492 logv("DMA is " + mDmaPackageName); 493 mDmaChangedListener = new DmaChangedListener(); 494 mFeatureFactory = factory; 495 mRcsStats = rcsStats; 496 init(); 497 } 498 499 /** 500 * create an instance 501 */ make(PhoneGlobals app)502 public static RcsProvisioningMonitor make(PhoneGlobals app) { 503 if (sInstance == null) { 504 logd("RcsProvisioningMonitor created."); 505 HandlerThread handlerThread = new HandlerThread(TAG); 506 handlerThread.start(); 507 sInstance = new RcsProvisioningMonitor(app, handlerThread.getLooper(), 508 new RoleManagerAdapterImpl(app), RcsFeatureManager::getConnector, 509 RcsStats.getInstance()); 510 } 511 return sInstance; 512 } 513 514 /** 515 * get the instance 516 */ getInstance()517 public static RcsProvisioningMonitor getInstance() { 518 return sInstance; 519 } 520 init()521 private void init() { 522 logd("init."); 523 IntentFilter filter = new IntentFilter(); 524 filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 525 mPhone.registerReceiver(mReceiver, filter); 526 mTelephonyRegistryManager.addOnSubscriptionsChangedListener( 527 mSubChangedListener, mHandler::post); 528 mDmaChangedListener.register(); 529 //initialize configs for all active sub 530 onSubChanged(); 531 } 532 release()533 private void release() { 534 logd("release."); 535 mDmaChangedListener.unregister(); 536 mTelephonyRegistryManager.removeOnSubscriptionsChangedListener(mSubChangedListener); 537 mPhone.unregisterReceiver(mReceiver); 538 for (int i = 0; i < mRcsFeatureListeners.size(); i++) { 539 mRcsFeatureListeners.valueAt(i).destroy(); 540 } 541 mRcsFeatureListeners.clear(); 542 mRcsProvisioningInfos.forEach((k, v)->v.destroy()); 543 mRcsProvisioningInfos.clear(); 544 mCarrierSingleRegistrationEnabledOverride.clear(); 545 } 546 reset()547 private void reset() { 548 release(); 549 init(); 550 } 551 552 /** 553 * destroy the instance 554 */ 555 @VisibleForTesting destroy()556 public void destroy() { 557 logd("destroy it."); 558 release(); 559 mHandler.getLooper().quit(); 560 } 561 562 /** 563 * get the handler 564 */ 565 @VisibleForTesting getHandler()566 public Handler getHandler() { 567 return mHandler; 568 } 569 570 /** 571 * Gets the config for a subscription 572 */ 573 @VisibleForTesting getConfig(int subId)574 public byte[] getConfig(int subId) { 575 if (mRcsProvisioningInfos.containsKey(subId)) { 576 return mRcsProvisioningInfos.get(subId).getConfig(); 577 } 578 return null; 579 } 580 581 /** 582 * Returns whether Rcs Volte single registration is enabled for the sub. 583 */ isRcsVolteSingleRegistrationEnabled(int subId)584 public Boolean isRcsVolteSingleRegistrationEnabled(int subId) { 585 if (mRcsProvisioningInfos.containsKey(subId)) { 586 return mRcsProvisioningInfos.get(subId).getSingleRegistrationCapability() 587 == ProvisioningManager.STATUS_CAPABLE; 588 } 589 return null; 590 } 591 592 /** 593 * Called when the new rcs config is received 594 */ updateConfig(int subId, byte[] config, boolean isCompressed)595 public void updateConfig(int subId, byte[] config, boolean isCompressed) { 596 mHandler.sendMessage(mHandler.obtainMessage( 597 EVENT_CONFIG_RECEIVED, subId, isCompressed ? 1 : 0, config)); 598 } 599 600 /** 601 * Called when the application needs rcs re-config 602 */ requestReconfig(int subId)603 public void requestReconfig(int subId) { 604 mHandler.sendMessage(mHandler.obtainMessage(EVENT_RECONFIG_REQUEST, subId, 0)); 605 } 606 607 /** 608 * Called when the application registers rcs provisioning callback 609 */ registerRcsProvisioningCallback(int subId, IRcsConfigCallback cb)610 public boolean registerRcsProvisioningCallback(int subId, IRcsConfigCallback cb) { 611 RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId); 612 // should not happen in normal case 613 if (info == null) { 614 logd("fail to register rcs provisioning callback due to subscription unavailable"); 615 return false; 616 } 617 618 return info.addRcsConfigCallback(cb); 619 } 620 621 /** 622 * Called when the application unregisters rcs provisioning callback 623 */ unregisterRcsProvisioningCallback(int subId, IRcsConfigCallback cb)624 public boolean unregisterRcsProvisioningCallback(int subId, IRcsConfigCallback cb) { 625 RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId); 626 // should not happen in normal case 627 if (info == null) { 628 logd("fail to unregister rcs provisioning changed due to subscription unavailable"); 629 return false; 630 } 631 632 return info.removeRcsConfigCallback(cb); 633 } 634 635 /** 636 * Enables or disables test mode. 637 * 638 * <p> If test mode is enabled, any rcs config change will not update the database. 639 */ setTestModeEnabled(boolean enabled)640 public void setTestModeEnabled(boolean enabled) { 641 logv("setTestModeEnabled as " + enabled); 642 if (mTestModeEnabled != enabled) { 643 mTestModeEnabled = enabled; 644 mHandler.sendMessage(mHandler.obtainMessage(EVENT_RESET)); 645 } 646 } 647 648 649 /** 650 * Returns whether the test mode is enabled. 651 */ getTestModeEnabled()652 public boolean getTestModeEnabled() { 653 return mTestModeEnabled; 654 } 655 656 /** 657 * override the device config whether single registration is enabled 658 */ overrideDeviceSingleRegistrationEnabled(Boolean enabled)659 public void overrideDeviceSingleRegistrationEnabled(Boolean enabled) { 660 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DEVICE_CONFIG_OVERRIDE, enabled)); 661 } 662 663 /** 664 * Overrides the carrier config whether single registration is enabled 665 */ overrideCarrierSingleRegistrationEnabled(int subId, Boolean enabled)666 public boolean overrideCarrierSingleRegistrationEnabled(int subId, Boolean enabled) { 667 if (!mRcsProvisioningInfos.containsKey(subId)) { 668 return false; 669 } 670 mHandler.sendMessage(mHandler.obtainMessage( 671 EVENT_CARRIER_CONFIG_OVERRIDE, subId, 0, enabled)); 672 return true; 673 } 674 675 /** 676 * override the rcs feature validation result for a subscription 677 */ overrideImsFeatureValidation(int subId, Boolean enabled)678 public boolean overrideImsFeatureValidation(int subId, Boolean enabled) { 679 if (enabled == null) { 680 mImsFeatureValidationOverride.remove(subId); 681 } else { 682 mImsFeatureValidationOverride.put(subId, enabled); 683 } 684 return true; 685 } 686 687 /** 688 * Returns the device config whether single registration is enabled 689 */ getDeviceSingleRegistrationEnabled()690 public boolean getDeviceSingleRegistrationEnabled() { 691 for (RcsProvisioningInfo info : mRcsProvisioningInfos.values()) { 692 return (info.getSingleRegistrationCapability() 693 & ProvisioningManager.STATUS_DEVICE_NOT_CAPABLE) == 0; 694 } 695 return false; 696 } 697 698 /** 699 * Returns the carrier config whether single registration is enabled 700 */ getCarrierSingleRegistrationEnabled(int subId)701 public boolean getCarrierSingleRegistrationEnabled(int subId) { 702 if (mRcsProvisioningInfos.containsKey(subId)) { 703 return (mRcsProvisioningInfos.get(subId).getSingleRegistrationCapability() 704 & ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE) == 0; 705 } 706 return false; 707 } 708 709 /** 710 * Returns the rcs feature validation override value, null if it is not set. 711 */ getImsFeatureValidationOverride(int subId)712 public Boolean getImsFeatureValidationOverride(int subId) { 713 return mImsFeatureValidationOverride.get(subId); 714 } 715 onDefaultMessagingApplicationChanged()716 private void onDefaultMessagingApplicationChanged() { 717 final String packageName = getDmaPackageName(); 718 if (!TextUtils.equals(mDmaPackageName, packageName)) { 719 mDmaPackageName = packageName; 720 logv("new default messaging application " + mDmaPackageName); 721 722 mRcsProvisioningInfos.forEach((k, v) -> { 723 v.notifyDma(); 724 725 byte[] cachedConfig = v.getConfig(); 726 //clear old callbacks 727 v.clear(); 728 if (isAcsUsed(k)) { 729 logv("acs used, trigger to re-configure."); 730 updateConfigForSub(k, null, true); 731 v.triggerRcsReconfiguration(); 732 } else { 733 logv("acs not used, set cached config and notify."); 734 v.setConfig(cachedConfig); 735 } 736 737 // store RCS metrics - DMA changed event 738 mRcsStats.onRcsClientProvisioningStats(k, 739 RCS_CLIENT_PROVISIONING_STATS__EVENT__DMA_CHANGED); 740 }); 741 } 742 } 743 updateConfigForSub(int subId, byte[] config, boolean isCompressed)744 private void updateConfigForSub(int subId, byte[] config, boolean isCompressed) { 745 logv("updateConfigForSub, subId:" + subId + ", mTestModeEnabled:" + mTestModeEnabled); 746 if (!mTestModeEnabled) { 747 RcsConfig.updateConfigForSub(mPhone, subId, config, isCompressed); 748 } 749 } 750 loadConfigForSub(int subId)751 private byte[] loadConfigForSub(int subId) { 752 logv("loadConfigForSub, subId:" + subId + ", mTestModeEnabled:" + mTestModeEnabled); 753 if (!mTestModeEnabled) { 754 return RcsConfig.loadRcsConfigForSub(mPhone, subId, false); 755 } 756 return null; 757 } 758 isAcsUsed(int subId)759 private boolean isAcsUsed(int subId) { 760 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(subId); 761 if (b == null) { 762 return false; 763 } 764 return b.getBoolean(CarrierConfigManager.KEY_USE_ACS_FOR_RCS_BOOL); 765 } 766 getSingleRegistrationRequiredByCarrier(int subId)767 private int getSingleRegistrationRequiredByCarrier(int subId) { 768 Boolean enabledByOverride = mCarrierSingleRegistrationEnabledOverride.get(subId); 769 if (enabledByOverride != null) { 770 return enabledByOverride ? ProvisioningManager.STATUS_CAPABLE 771 : ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE; 772 } 773 774 PersistableBundle b = mCarrierConfigManager.getConfigForSubId(subId); 775 if (!CarrierConfigManager.isConfigForIdentifiedCarrier(b)) { 776 return MASK_CAP_CARRIER_INIT; 777 } 778 return b.getBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL) 779 ? ProvisioningManager.STATUS_CAPABLE 780 : ProvisioningManager.STATUS_CARRIER_NOT_CAPABLE; 781 } 782 getSingleRegistrationCapableValue(int subId)783 private int getSingleRegistrationCapableValue(int subId) { 784 boolean isSingleRegistrationEnabledOnDevice = 785 mDeviceSingleRegistrationEnabledOverride != null 786 ? mDeviceSingleRegistrationEnabledOverride 787 : mPhone.getPackageManager().hasSystemFeature( 788 PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION); 789 790 int value = (isSingleRegistrationEnabledOnDevice ? ProvisioningManager.STATUS_CAPABLE 791 : ProvisioningManager.STATUS_DEVICE_NOT_CAPABLE) 792 | getSingleRegistrationRequiredByCarrier(subId); 793 logv("SingleRegistrationCapableValue : " + value); 794 return value; 795 } 796 onCarrierConfigChange()797 private void onCarrierConfigChange() { 798 logv("onCarrierConfigChange"); 799 mRcsProvisioningInfos.forEach((subId, info) -> { 800 info.setSingleRegistrationCapability( 801 getSingleRegistrationCapableValue(subId)); 802 }); 803 } 804 onSubChanged()805 private void onSubChanged() { 806 final int[] activeSubs = mSubscriptionManager.getActiveSubscriptionIdList(); 807 final ArraySet<Integer> subsToBeDeactivated = 808 new ArraySet<>(mRcsProvisioningInfos.keySet()); 809 810 for (int i : activeSubs) { 811 subsToBeDeactivated.remove(i); 812 if (!mRcsProvisioningInfos.containsKey(i)) { 813 byte[] data = loadConfigForSub(i); 814 int capability = getSingleRegistrationCapableValue(i); 815 logv("new info is created for sub : " + i + ", single registration capability :" 816 + capability + ", rcs config : " + Arrays.toString(data)); 817 mRcsProvisioningInfos.put(i, new RcsProvisioningInfo(i, capability, data)); 818 } 819 } 820 821 subsToBeDeactivated.forEach(i -> { 822 RcsProvisioningInfo info = mRcsProvisioningInfos.remove(i); 823 if (info != null) { 824 info.destroy(); 825 } 826 }); 827 } 828 onConfigReceived(int subId, byte[] config, boolean isCompressed)829 private void onConfigReceived(int subId, byte[] config, boolean isCompressed) { 830 logv("onConfigReceived, subId:" + subId + ", config:" 831 + Arrays.toString(config) + ", isCompressed:" + isCompressed); 832 RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId); 833 if (info == null) { 834 logd("sub[" + subId + "] has been removed"); 835 return; 836 } 837 info.setConfig(isCompressed ? RcsConfig.decompressGzip(config) : config); 838 updateConfigForSub(subId, config, isCompressed); 839 840 // Supporting ACS means config data comes from ACS 841 // store RCS metrics - received provisioning event 842 if (isAcsUsed(subId)) { 843 mRcsStats.onRcsAcsProvisioningStats(subId, 200, 844 RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML, 845 isRcsVolteSingleRegistrationEnabled(subId)); 846 } 847 } 848 onReconfigRequest(int subId)849 private void onReconfigRequest(int subId) { 850 logv("onReconfigRequest, subId:" + subId); 851 RcsProvisioningInfo info = mRcsProvisioningInfos.get(subId); 852 if (info != null) { 853 info.setConfig(null); 854 // clear rcs config stored in db 855 updateConfigForSub(subId, null, true); 856 info.triggerRcsReconfiguration(); 857 } 858 859 // store RCS metrics - reconfig event 860 mRcsStats.onRcsClientProvisioningStats(subId, 861 RCS_CLIENT_PROVISIONING_STATS__EVENT__TRIGGER_RCS_RECONFIGURATION); 862 } 863 notifyDmaForSub(int subId, int capability)864 private void notifyDmaForSub(int subId, int capability) { 865 final Intent intent = new Intent( 866 ProvisioningManager.ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE); 867 intent.setPackage(mDmaPackageName); 868 intent.putExtra(ProvisioningManager.EXTRA_SUBSCRIPTION_ID, subId); 869 intent.putExtra(ProvisioningManager.EXTRA_STATUS, capability); 870 logv("notify " + intent + ", sub:" + subId + ", capability:" + capability); 871 // Only send permission to the default sms app if it has the correct permissions 872 // except test mode enabled 873 if (!mTestModeEnabled) { 874 mPhone.sendBroadcast(intent, Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION); 875 } else { 876 mPhone.sendBroadcast(intent); 877 } 878 } 879 getDmaPackageName()880 private String getDmaPackageName() { 881 try { 882 return CollectionUtils.firstOrNull(mRoleManager.getRoleHolders(RoleManager.ROLE_SMS)); 883 } catch (RuntimeException e) { 884 loge("Could not get dma name due to " + e); 885 return null; 886 } 887 } 888 registerRcsFeatureListener(RcsProvisioningInfo info)889 void registerRcsFeatureListener(RcsProvisioningInfo info) { 890 int slotId = SubscriptionManager.getSlotIndex(info.getSubId()); 891 RcsFeatureListener cb = mRcsFeatureListeners.get(slotId); 892 if (cb == null) { 893 cb = new RcsFeatureListener(slotId); 894 mRcsFeatureListeners.put(slotId, cb); 895 } 896 cb.addRcsProvisioningInfo(info); 897 } 898 unregisterRcsFeatureListener(RcsProvisioningInfo info)899 void unregisterRcsFeatureListener(RcsProvisioningInfo info) { 900 // make sure the info to be removed in any case, even the slotId changed or invalid. 901 for (int i = 0; i < mRcsFeatureListeners.size(); i++) { 902 mRcsFeatureListeners.valueAt(i).removeRcsProvisioningInfo(info); 903 } 904 } 905 booleanEquals(Boolean val1, Boolean val2)906 private static boolean booleanEquals(Boolean val1, Boolean val2) { 907 return (val1 == null && val2 == null) 908 || (Boolean.TRUE.equals(val1) && Boolean.TRUE.equals(val2)) 909 || (Boolean.FALSE.equals(val1) && Boolean.FALSE.equals(val2)); 910 } 911 logv(String msg)912 private static void logv(String msg) { 913 if (DBG) { 914 Rlog.d(TAG, msg); 915 } 916 } 917 logi(String msg)918 private static void logi(String msg) { 919 Rlog.i(TAG, msg); 920 } 921 logd(String msg)922 private static void logd(String msg) { 923 Rlog.d(TAG, msg); 924 } 925 loge(String msg)926 private static void loge(String msg) { 927 Rlog.e(TAG, msg); 928 } 929 930 /** 931 * {@link RoleManager} is final so we have to wrap the implementation for testing. 932 */ 933 @VisibleForTesting 934 public interface RoleManagerAdapter { 935 /** See {@link RoleManager#getRoleHolders(String)} */ getRoleHolders(String roleName)936 List<String> getRoleHolders(String roleName); 937 /** See {@link RoleManager#addOnRoleHoldersChangedListenerAsUser} */ addOnRoleHoldersChangedListenerAsUser(Executor executor, OnRoleHoldersChangedListener listener, UserHandle user)938 void addOnRoleHoldersChangedListenerAsUser(Executor executor, 939 OnRoleHoldersChangedListener listener, UserHandle user); 940 /** See {@link RoleManager#removeOnRoleHoldersChangedListenerAsUser} */ removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener, UserHandle user)941 void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener, 942 UserHandle user); 943 } 944 945 private static class RoleManagerAdapterImpl implements RoleManagerAdapter { 946 private final RoleManager mRoleManager; 947 RoleManagerAdapterImpl(Context context)948 private RoleManagerAdapterImpl(Context context) { 949 mRoleManager = context.getSystemService(RoleManager.class); 950 } 951 952 @Override getRoleHolders(String roleName)953 public List<String> getRoleHolders(String roleName) { 954 return mRoleManager.getRoleHolders(roleName); 955 } 956 957 @Override addOnRoleHoldersChangedListenerAsUser(Executor executor, OnRoleHoldersChangedListener listener, UserHandle user)958 public void addOnRoleHoldersChangedListenerAsUser(Executor executor, 959 OnRoleHoldersChangedListener listener, UserHandle user) { 960 mRoleManager.addOnRoleHoldersChangedListenerAsUser(executor, listener, user); 961 } 962 963 @Override removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener, UserHandle user)964 public void removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener listener, 965 UserHandle user) { 966 mRoleManager.removeOnRoleHoldersChangedListenerAsUser(listener, user); 967 } 968 } 969 } 970