• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.content.Intent;
21 import android.content.pm.PackageManager;
22 import android.content.pm.ResolveInfo;
23 import android.os.PersistableBundle;
24 import android.provider.Settings;
25 import android.telecom.PhoneAccountHandle;
26 import android.telecom.TelecomManager;
27 import android.telephony.CarrierConfigManager;
28 import android.telephony.PhoneStateListener;
29 import android.telephony.SubscriptionManager;
30 import android.telephony.TelephonyCallback;
31 import android.telephony.TelephonyManager;
32 import android.telephony.ims.ImsMmTelManager;
33 import android.util.Log;
34 
35 import androidx.annotation.VisibleForTesting;
36 import androidx.preference.Preference;
37 import androidx.preference.PreferenceScreen;
38 
39 import com.android.settings.R;
40 import com.android.settings.network.ims.WifiCallingQueryImsState;
41 import com.android.settingslib.core.lifecycle.LifecycleObserver;
42 import com.android.settingslib.core.lifecycle.events.OnStart;
43 import com.android.settingslib.core.lifecycle.events.OnStop;
44 
45 import java.util.List;
46 
47 /**
48  * Preference controller for "Wifi Calling"
49  */
50 //TODO: Remove the class once Provider Model is always enabled in the future.
51 public class WifiCallingPreferenceController extends TelephonyBasePreferenceController implements
52         LifecycleObserver, OnStart, OnStop {
53 
54     private static final String TAG = "WifiCallingPreference";
55 
56     @VisibleForTesting
57     Integer mCallState;
58     @VisibleForTesting
59     CarrierConfigManager mCarrierConfigManager;
60     private ImsMmTelManager mImsMmTelManager;
61     @VisibleForTesting
62     PhoneAccountHandle mSimCallManager;
63     private PhoneTelephonyCallback mTelephonyCallback;
64     private Preference mPreference;
65 
WifiCallingPreferenceController(Context context, String key)66     public WifiCallingPreferenceController(Context context, String key) {
67         super(context, key);
68         mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
69         mTelephonyCallback = new PhoneTelephonyCallback();
70     }
71 
72     @Override
getAvailabilityStatus(int subId)73     public int getAvailabilityStatus(int subId) {
74         return SubscriptionManager.isValidSubscriptionId(subId)
75                 && MobileNetworkUtils.isWifiCallingEnabled(mContext, subId, null, null)
76                 ? AVAILABLE
77                 : UNSUPPORTED_ON_DEVICE;
78     }
79 
80     @Override
onStart()81     public void onStart() {
82         mTelephonyCallback.register(mContext, mSubId);
83     }
84 
85     @Override
onStop()86     public void onStop() {
87         mTelephonyCallback.unregister();
88     }
89 
90     @Override
displayPreference(PreferenceScreen screen)91     public void displayPreference(PreferenceScreen screen) {
92         super.displayPreference(screen);
93         mPreference = screen.findPreference(getPreferenceKey());
94         final Intent intent = mPreference.getIntent();
95         if (intent != null) {
96             intent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
97         }
98     }
99 
100     @Override
updateState(Preference preference)101     public void updateState(Preference preference) {
102         super.updateState(preference);
103         if ((mCallState == null) || (preference == null)) {
104             Log.d(TAG, "Skip update under mCallState=" + mCallState);
105             return;
106         }
107         CharSequence summaryText = null;
108         if (mSimCallManager != null) {
109             final Intent intent = MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext,
110                     mSimCallManager);
111             if (intent == null) {
112                 // Do nothing in this case since preference is invisible
113                 return;
114             }
115             final PackageManager pm = mContext.getPackageManager();
116             final List<ResolveInfo> resolutions = pm.queryIntentActivities(intent, 0);
117             preference.setTitle(resolutions.get(0).loadLabel(pm));
118             preference.setIntent(intent);
119         } else {
120             final String title = SubscriptionManager.getResourcesForSubId(mContext, mSubId)
121                     .getString(R.string.wifi_calling_settings_title);
122             preference.setTitle(title);
123             summaryText = getResourceIdForWfcMode(mSubId);
124         }
125         preference.setSummary(summaryText);
126         preference.setEnabled(mCallState == TelephonyManager.CALL_STATE_IDLE);
127     }
128 
getResourceIdForWfcMode(int subId)129     private CharSequence getResourceIdForWfcMode(int subId) {
130         int resId = com.android.internal.R.string.wifi_calling_off_summary;
131         if (queryImsState(subId).isEnabledByUser()) {
132             boolean useWfcHomeModeForRoaming = false;
133             if (mCarrierConfigManager != null) {
134                 final PersistableBundle carrierConfig =
135                         mCarrierConfigManager.getConfigForSubId(subId);
136                 if (carrierConfig != null) {
137                     useWfcHomeModeForRoaming = carrierConfig.getBoolean(
138                             CarrierConfigManager
139                                     .KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL);
140                 }
141             }
142             final boolean isRoaming = getTelephonyManager(mContext, subId)
143                     .isNetworkRoaming();
144             final int wfcMode = (isRoaming && !useWfcHomeModeForRoaming)
145                     ? mImsMmTelManager.getVoWiFiRoamingModeSetting() :
146                     mImsMmTelManager.getVoWiFiModeSetting();
147             switch (wfcMode) {
148                 case ImsMmTelManager.WIFI_MODE_WIFI_ONLY:
149                     resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
150                     break;
151                 case ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED:
152                     resId = com.android.internal.R.string
153                             .wfc_mode_cellular_preferred_summary;
154                     break;
155                 case ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED:
156                     resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary;
157                     break;
158                 default:
159                     break;
160             }
161         }
162         return SubscriptionManager.getResourcesForSubId(mContext, subId).getText(resId);
163     }
164 
init(int subId)165     public WifiCallingPreferenceController init(int subId) {
166         mSubId = subId;
167         mImsMmTelManager = getImsMmTelManager(mSubId);
168         mSimCallManager = mContext.getSystemService(TelecomManager.class)
169                 .getSimCallManagerForSubscription(mSubId);
170 
171         return this;
172     }
173 
174     @VisibleForTesting
queryImsState(int subId)175     WifiCallingQueryImsState queryImsState(int subId) {
176         return new WifiCallingQueryImsState(mContext, subId);
177     }
178 
getImsMmTelManager(int subId)179     protected ImsMmTelManager getImsMmTelManager(int subId) {
180         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
181             return null;
182         }
183         return ImsMmTelManager.createForSubscriptionId(subId);
184     }
185 
186     @VisibleForTesting
getTelephonyManager(Context context, int subId)187     TelephonyManager getTelephonyManager(Context context, int subId) {
188         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
189         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
190             return telephonyMgr;
191         }
192         final TelephonyManager subscriptionTelephonyMgr =
193                 telephonyMgr.createForSubscriptionId(subId);
194         return (subscriptionTelephonyMgr == null) ? telephonyMgr : subscriptionTelephonyMgr;
195     }
196 
197 
198     private class PhoneTelephonyCallback extends TelephonyCallback implements
199             TelephonyCallback.CallStateListener {
200 
201         private TelephonyManager mTelephonyManager;
202 
203         @Override
onCallStateChanged(int state)204         public void onCallStateChanged(int state) {
205             mCallState = state;
206             updateState(mPreference);
207         }
208 
register(Context context, int subId)209         public void register(Context context, int subId) {
210             mTelephonyManager = getTelephonyManager(context, subId);
211             // assign current call state so that it helps to show correct preference state even
212             // before first onCallStateChanged() by initial registration.
213             mCallState = mTelephonyManager.getCallState(subId);
214             mTelephonyManager.registerTelephonyCallback(context.getMainExecutor(), this);
215         }
216 
unregister()217         public void unregister() {
218             mCallState = null;
219             mTelephonyManager.unregisterTelephonyCallback(this);
220         }
221     }
222 }
223