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