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