1 /*
2  * Copyright (C) 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.settings.network.telephony;
18 
19 import android.content.Context;
20 import android.database.ContentObserver;
21 import android.net.Uri;
22 import android.os.PersistableBundle;
23 import android.provider.Telephony;
24 import android.telephony.CarrierConfigManager;
25 import android.telephony.SubscriptionInfo;
26 import android.telephony.ims.ImsManager;
27 import android.util.Log;
28 
29 import androidx.annotation.VisibleForTesting;
30 import androidx.fragment.app.FragmentManager;
31 import androidx.lifecycle.Lifecycle;
32 import androidx.lifecycle.LifecycleObserver;
33 import androidx.lifecycle.OnLifecycleEvent;
34 import androidx.preference.Preference;
35 import androidx.preference.PreferenceScreen;
36 import androidx.preference.TwoStatePreference;
37 
38 import com.android.settings.network.CarrierConfigCache;
39 import com.android.settings.network.SubscriptionUtil;
40 
41 /**
42  * Controller for the "Contact Discovery" option present in MobileNetworkSettings.
43  */
44 public class ContactDiscoveryPreferenceController extends TelephonyTogglePreferenceController
45         implements LifecycleObserver {
46     private static final String TAG = "ContactDiscoveryPref";
47     private static final Uri UCE_URI = Uri.withAppendedPath(Telephony.SimInfo.CONTENT_URI,
48             Telephony.SimInfo.COLUMN_IMS_RCS_UCE_ENABLED);
49 
50     private ImsManager mImsManager;
51     private CarrierConfigCache mCarrierConfigCache;
52     private ContentObserver mUceSettingObserver;
53     private FragmentManager mFragmentManager;
54 
55     @VisibleForTesting
56     public Preference preference;
57 
ContactDiscoveryPreferenceController(Context context, String key)58     public ContactDiscoveryPreferenceController(Context context, String key) {
59         super(context, key);
60         mImsManager = mContext.getSystemService(ImsManager.class);
61         mCarrierConfigCache = CarrierConfigCache.getInstance(context);
62     }
63 
init(FragmentManager fragmentManager, int subId)64     void init(FragmentManager fragmentManager, int subId) {
65         mFragmentManager = fragmentManager;
66         mSubId = subId;
67     }
68 
69     @Override
isChecked()70     public boolean isChecked() {
71         return MobileNetworkUtils.isContactDiscoveryEnabled(mImsManager, mSubId);
72     }
73 
74     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
onResume()75     public void onResume() {
76         registerUceObserver();
77     }
78 
79     @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
onPause()80     public void onPause() {
81         unregisterUceObserver();
82     }
83 
84     @Override
setChecked(boolean isChecked)85     public boolean setChecked(boolean isChecked) {
86         if (isChecked) {
87             showContentDiscoveryDialog();
88             // launch dialog and wait for activity to return and ContentObserver to fire to update.
89             return false;
90         }
91         MobileNetworkUtils.setContactDiscoveryEnabled(mImsManager, mSubId, false /*isEnabled*/);
92         return true;
93     }
94 
95     @Override
getAvailabilityStatus(int subId)96     public int getAvailabilityStatus(int subId) {
97         PersistableBundle bundle = mCarrierConfigCache.getConfigForSubId(subId);
98         boolean shouldShowPresence = bundle != null
99                 && (bundle.getBoolean(
100                 CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false /*default*/)
101                 || bundle.getBoolean(
102                 CarrierConfigManager.Ims.KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false /*default*/));
103         return shouldShowPresence ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
104     }
105 
106     @Override
displayPreference(PreferenceScreen screen)107     public void displayPreference(PreferenceScreen screen) {
108         super.displayPreference(screen);
109         preference = screen.findPreference(getPreferenceKey());
110     }
111 
registerUceObserver()112     private void registerUceObserver() {
113         mUceSettingObserver = new ContentObserver(mContext.getMainThreadHandler()) {
114             @Override
115             public void onChange(boolean selfChange) {
116                 onChange(selfChange, null /*uri*/);
117             }
118 
119             @Override
120             public void onChange(boolean selfChange, Uri uri) {
121                 Log.d(TAG, "UCE setting changed, re-evaluating.");
122                 TwoStatePreference switchPref = (TwoStatePreference) preference;
123                 switchPref.setChecked(isChecked());
124             }
125         };
126         mContext.getContentResolver().registerContentObserver(UCE_URI, true /*notifyForDecendants*/,
127                 mUceSettingObserver);
128     }
129 
unregisterUceObserver()130     private void unregisterUceObserver() {
131         mContext.getContentResolver().unregisterContentObserver(mUceSettingObserver);
132     }
133 
showContentDiscoveryDialog()134     private void showContentDiscoveryDialog() {
135         ContactDiscoveryDialogFragment dialog = ContactDiscoveryDialogFragment.newInstance(
136                 mSubId, getCarrierDisplayName(preference.getContext()));
137         dialog.show(mFragmentManager, ContactDiscoveryDialogFragment.getFragmentTag(mSubId));
138     }
139 
getCarrierDisplayName(Context context)140     private CharSequence getCarrierDisplayName(Context context) {
141         CharSequence result = "";
142 
143         for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(context)) {
144             if (mSubId == info.getSubscriptionId()) {
145                 result = SubscriptionUtil.getUniqueSubscriptionDisplayName(info, context);
146                 break;
147             }
148         }
149         return result;
150     }
151 }
152