diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml
index 08b3fbcffe6..43cadab7671 100644
--- a/res/xml/network_setting_fragment.xml
+++ b/res/xml/network_setting_fragment.xml
@@ -82,20 +82,20 @@
-
+ android:title="@string/wifi_calling_settings_title"
+ settings:controller="com.android.settings.network.telephony.WifiCallingPreferenceController" >
-
+ android:persistent="true"
+ settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController" />
diff --git a/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java b/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java
index 0a258ec335a..cc8e78d06da 100644
--- a/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java
+++ b/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java
@@ -36,6 +36,9 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Preference controller for "Enhanced 4G LTE"
*/
@@ -49,13 +52,15 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle
@VisibleForTesting
ImsManager mImsManager;
private PhoneCallStateListener mPhoneStateListener;
+ private final List m4gLteListeners;
private int mSubId;
public Enhanced4gLtePreferenceController(Context context, String key) {
super(context, key);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
+ m4gLteListeners = new ArrayList<>();
mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
- mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
@Override
@@ -105,6 +110,9 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle
@Override
public boolean setChecked(boolean isChecked) {
mImsManager.setEnhanced4gLteModeSetting(isChecked);
+ for (final On4gLteUpdateListener lsn : m4gLteListeners) {
+ lsn.on4gLteUpdated();
+ }
return true;
}
@@ -113,13 +121,20 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle
return mImsManager.isEnhanced4gLteModeSettingEnabledByUser();
}
- public void init(int subId) {
+ public Enhanced4gLtePreferenceController init(int subId) {
mSubId = subId;
mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
}
+
+ return this;
+ }
+
+ public Enhanced4gLtePreferenceController addListener(On4gLteUpdateListener lsn) {
+ m4gLteListeners.add(lsn);
+ return this;
}
private boolean is4gLtePrefEnabled() {
@@ -151,4 +166,11 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle
mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
}
}
+
+ /**
+ * Update other preferences when 4gLte state is changed
+ */
+ public interface On4gLteUpdateListener {
+ void on4gLteUpdated();
+ }
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkFragment.java b/src/com/android/settings/network/telephony/MobileNetworkFragment.java
index 3d005510577..b31c1a10991 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkFragment.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkFragment.java
@@ -26,22 +26,17 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.Message;
import android.os.PersistableBundle;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
-import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.MenuItem;
@@ -51,9 +46,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
@@ -93,8 +86,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
private static final String BUTTON_CARRIER_SETTINGS_EUICC_KEY =
"carrier_settings_euicc_key";
- private static final String BUTTON_WIFI_CALLING_KEY = "wifi_calling_key";
- private static final String BUTTON_VIDEO_CALLING_KEY = "video_calling_key";
private static final String BUTTON_MOBILE_DATA_ENABLE_KEY = "mobile_data_enable";
private static final String BUTTON_DATA_USAGE_KEY = "data_usage_summary";
private static final String BUTTON_ADVANCED_OPTIONS_KEY = "advanced_options";
@@ -120,13 +111,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
private CarrierConfigManager mCarrierConfigManager;
private int mSubId;
- //UI objects
- private SwitchPreference mButton4glte;
- private PreferenceCategory mCallingCategory;
- private Preference mWiFiCallingPref;
- private SwitchPreference mVideoCallingPref;
- private NetworkSelectListPreference mButtonNetworkSelect;
-
private CdmaSystemSelectPreferenceController mCdmaSystemSelectPreferenceController;
private CdmaSubscriptionPreferenceController mCdmaSubscriptionPreferenceController;
@@ -147,44 +131,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
private boolean mOnlyAutoSelectInHomeNW;
private boolean mUnavailable;
- private class PhoneCallStateListener extends PhoneStateListener {
- /*
- * Enable/disable the 'Enhanced 4G LTE Mode' when in/out of a call
- * and depending on TTY mode and TTY support over VoLTE.
- * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
- * java.lang.String)
- */
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- if (DBG) log("PhoneStateListener.onCallStateChanged: state=" + state);
-
- updateWiFiCallState();
- updateVideoCallState();
- updatePreferredNetworkType();
- }
-
- /**
- * Listen to different subId if it's changed.
- */
- protected void updateSubscriptionId(Integer subId) {
- if (subId.equals(PhoneCallStateListener.this.mSubId)) {
- return;
- }
-
- PhoneCallStateListener.this.mSubId = subId;
-
- mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
-
- // Now, listen to new subId if it's valid.
- if (SubscriptionManager.isValidSubscriptionId(subId)) {
- mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
- }
- }
- }
-
- private final PhoneCallStateListener
- mPhoneStateListener = new PhoneCallStateListener();
-
@Override
public int getMetricsCategory() {
//TODO(b/114749736): add metrics id for it
@@ -221,11 +167,9 @@ public class MobileNetworkFragment extends DashboardFragment implements
REQUEST_CODE_EXIT_ECM);
}
return true;
- } else if (preference == mWiFiCallingPref || preference == mVideoCallingPref) {
- return false;
}
- return true;
+ return false;
}
private final SubscriptionManager.OnSubscriptionsChangedListener
@@ -255,8 +199,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
SubscriptionManager.getPhoneId(mSubId));
mTelephonyManager = new TelephonyManager(getContext(), mSubId);
}
-
- mPhoneStateListener.updateSubscriptionId(mSubId);
}
@Override
@@ -272,14 +214,19 @@ public class MobileNetworkFragment extends DashboardFragment implements
use(DataUsagePreferenceController.class).init(mSubId);
use(PreferredNetworkModePreferenceController.class).init(mSubId);
use(EnabledNetworkModePreferenceController.class).init(mSubId);
- use(Enhanced4gLtePreferenceController.class).init(mSubId);
use(DataServiceSetupPreferenceController.class).init(mSubId);
use(EuiccPreferenceController.class).init(mSubId);
+ use(WifiCallingPreferenceController.class).init(mSubId);
mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class);
mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId);
mCdmaSubscriptionPreferenceController = use(CdmaSubscriptionPreferenceController.class);
mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId);
+
+ final VideoCallingPreferenceController videoCallingPreferenceController =
+ use(VideoCallingPreferenceController.class).init(mSubId);
+ use(Enhanced4gLtePreferenceController.class).init(mSubId)
+ .addListener(videoCallingPreferenceController);
}
@Override
@@ -299,12 +246,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
Context.TELEPHONY_SERVICE);
mCarrierConfigManager = new CarrierConfigManager(getContext());
- mButton4glte = (SwitchPreference)findPreference(BUTTON_4G_LTE_KEY);
-
- mCallingCategory = (PreferenceCategory) findPreference(CATEGORY_CALLING_KEY);
- mWiFiCallingPref = findPreference(BUTTON_WIFI_CALLING_KEY);
- mVideoCallingPref = (SwitchPreference) findPreference(BUTTON_VIDEO_CALLING_KEY);
-
try {
Context con = context.createPackageContext("com.android.systemui", 0);
int id = con.getResources().getIdentifier("config_show4GForLTE",
@@ -378,11 +319,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
// preferences.
getPreferenceScreen().setEnabled(true);
- mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
-
- // Video calling and WiFi calling state might have changed.
- updateCallingCategory();
-
mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
final Context context = getContext();
@@ -492,9 +428,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
android.provider.Settings.Global.getString(activity.getContentResolver(),
android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL));
- updatePreferredNetworkType();
- updateCallingCategory();
-
// Enable link to CMAS app settings depending on the value in config.xml.
final boolean isCellBroadcastAppLinkEnabled = activity.getResources().getBoolean(
com.android.internal.R.bool.config_cellBroadcastAppLinks);
@@ -555,8 +488,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
super.onPause();
if (DBG) log("onPause:+");
- mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
-
mSubscriptionManager
.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
@@ -576,18 +507,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
*/
public boolean onPreferenceChange(Preference preference, Object objValue) {
sendMetricsEventPreferenceChanged(getPreferenceScreen(), preference, objValue);
- if (preference == mVideoCallingPref) {
- // If mButton4glte is not checked, mVideoCallingPref should be disabled.
- // So it only makes sense to call phoneMgr.enableVideoCalling if it's checked.
- if (mButton4glte.isChecked()) {
- mImsMgr.setVtSetting((boolean) objValue);
- return true;
- } else {
- loge("mVideoCallingPref should be disabled if mButton4glte is not checked.");
- mVideoCallingPref.setEnabled(false);
- return false;
- }
- }
updateBody();
// always let the preference setting proceed.
@@ -629,111 +548,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
}
}
- private void updateWiFiCallState() {
- if (mWiFiCallingPref == null || mCallingCategory == null) {
- return;
- }
-
- // Removes the preference if the wifi calling is disabled.
- if (!MobileNetworkUtils.isWifiCallingEnabled(getContext(),
- SubscriptionManager.getPhoneId(mSubId))) {
- mCallingCategory.removePreference(mWiFiCallingPref);
- return;
- }
-
- final PhoneAccountHandle simCallManager =
- TelecomManager.from(getContext()).getSimCallManager();
-
- if (simCallManager != null) {
- Intent intent = buildPhoneAccountConfigureIntent(getContext(), simCallManager);
- PackageManager pm = getContext().getPackageManager();
- List resolutions = pm.queryIntentActivities(intent, 0);
- mWiFiCallingPref.setTitle(resolutions.get(0).loadLabel(pm));
- mWiFiCallingPref.setSummary(null);
- mWiFiCallingPref.setIntent(intent);
- } else {
- int resId = com.android.internal.R.string.wifi_calling_off_summary;
- if (mImsMgr.isWfcEnabledByUser()) {
- boolean isRoaming = mTelephonyManager.isNetworkRoaming();
- int wfcMode = mImsMgr.getWfcMode(isRoaming);
-
- switch (wfcMode) {
- case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
- resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
- break;
- case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
- resId = com.android.internal.R.string
- .wfc_mode_cellular_preferred_summary;
- break;
- case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
- resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary;
- break;
- default:
- if (DBG) log("Unexpected WFC mode value: " + wfcMode);
- }
- }
- mWiFiCallingPref.setSummary(resId);
- }
-
- mCallingCategory.addPreference(mWiFiCallingPref);
- mWiFiCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId)
- == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions());
- }
-
- private void updateVideoCallState() {
- if (mVideoCallingPref == null || mCallingCategory == null) {
- return;
- }
-
- PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
-
- if (mImsMgr != null
- && mImsMgr.isVtEnabledByPlatform()
- && mImsMgr.isVtProvisionedOnDevice()
- && MobileNetworkUtils.isImsServiceStateReady(mImsMgr)
- && (carrierConfig.getBoolean(
- CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
- || mTelephonyManager.isDataEnabled())) {
- mCallingCategory.addPreference(mVideoCallingPref);
- if (!mButton4glte.isChecked()) {
- mVideoCallingPref.setEnabled(false);
- mVideoCallingPref.setChecked(false);
- } else {
- mVideoCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId)
- == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions());
- mVideoCallingPref.setChecked(mImsMgr.isVtEnabledByUser());
- mVideoCallingPref.setOnPreferenceChangeListener(this);
- }
- } else {
- mCallingCategory.removePreference(mVideoCallingPref);
- }
- }
-
- private void updatePreferredNetworkType() {
- boolean enabled = mTelephonyManager.getCallState(
- mSubId) == TelephonyManager.CALL_STATE_IDLE
- && hasActiveSubscriptions();
- Log.i(LOG_TAG, "updatePreferredNetworkType: " + enabled);
- }
-
- private void updateCallingCategory() {
- if (mCallingCategory == null) {
- return;
- }
-
- updateWiFiCallState();
- updateVideoCallState();
-
- // If all items in calling category is removed, we remove it from
- // the screen. Otherwise we'll see title of the category but nothing
- // is in there.
- if (mCallingCategory.getPreferenceCount() == 0) {
- getPreferenceScreen().removePreference(mCallingCategory);
- } else {
- getPreferenceScreen().addPreference(mCallingCategory);
- }
- }
-
private static void log(String msg) {
Log.d(LOG_TAG, msg);
}
@@ -854,8 +668,7 @@ public class MobileNetworkFragment extends DashboardFragment implements
// For ListPreferences, we log it here without a value, only indicating it's clicked to
// open the list dialog. When a value is chosen, another MetricsEvent is logged with
// new value in onPreferenceChange.
- if (preference == mWiFiCallingPref
- || preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
+ if (preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
|| preference == preferenceScreen.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)
|| preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY)
|| preference == preferenceScreen.findPreference(BUTTON_CDMA_APN_EXPAND_KEY)
@@ -872,9 +685,7 @@ public class MobileNetworkFragment extends DashboardFragment implements
}
// MetricsEvent logging with new value, for SwitchPreferences and ListPreferences.
- if (preference == mVideoCallingPref) {
- MetricsLogger.action(getContext(), category, (Boolean) newValue);
- } else if (preference == preferenceScreen
+ if (preference == preferenceScreen
.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
|| preference == preferenceScreen
.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
@@ -888,10 +699,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
if (preference == null) {
return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
- } else if (preference == mWiFiCallingPref) {
- return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_WIFI_CALLING;
- } else if (preference == mVideoCallingPref) {
- return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_VIDEO_CALLING_TOGGLE;
} else if (preference == preferenceScreen
.findPreference(NetworkOperators.BUTTON_AUTO_SELECT_KEY)) {
return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE;
@@ -995,31 +802,4 @@ public class MobileNetworkFragment extends DashboardFragment implements
return result;
}
};
-
- private static final class SetPreferredNetworkAsyncTask extends AsyncTask {
-
- private final TelephonyManager mTelephonyManager;
- private final int mSubId;
- private final int mNetworkType;
- private final Message mCallback;
-
- SetPreferredNetworkAsyncTask(
- TelephonyManager tm, int subId, int networkType, Message callback) {
- mTelephonyManager = tm;
- mSubId = subId;
- mNetworkType = networkType;
- mCallback = callback;
- }
-
- @Override
- protected Boolean doInBackground(Void... voids) {
- return mTelephonyManager.setPreferredNetworkType(mSubId, mNetworkType);
- }
-
- @Override
- protected void onPostExecute(Boolean isSuccessed) {
- mCallback.obj = isSuccessed;
- mCallback.sendToTarget();
- }
- }
}
diff --git a/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java
new file mode 100644
index 00000000000..1007ef8e03a
--- /dev/null
+++ b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.provider.Settings;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.ims.ImsManager;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+/**
+ * Preference controller for "Video Calling"
+ */
+public class VideoCallingPreferenceController extends TogglePreferenceController implements
+ LifecycleObserver, OnStart, OnStop,
+ Enhanced4gLtePreferenceController.On4gLteUpdateListener {
+
+ private Preference mPreference;
+ private TelephonyManager mTelephonyManager;
+ private CarrierConfigManager mCarrierConfigManager;
+ private PersistableBundle mCarrierConfig;
+ @VisibleForTesting
+ ImsManager mImsManager;
+ private PhoneCallStateListener mPhoneStateListener;
+ private DataContentObserver mDataContentObserver;
+ private int mSubId;
+
+ public VideoCallingPreferenceController(Context context, String key) {
+ super(context, key);
+ mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
+ mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper()));
+ mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
+ mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ && MobileNetworkUtils.isWifiCallingEnabled(mContext,
+ SubscriptionManager.getPhoneId(mSubId))
+ && isVideoCallEnabled()
+ ? AVAILABLE
+ : CONDITIONALLY_UNAVAILABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public void onStart() {
+ mPhoneStateListener.register(mSubId);
+ mDataContentObserver.register(mContext, mSubId);
+ }
+
+ @Override
+ public void onStop() {
+ mPhoneStateListener.unregister();
+ mDataContentObserver.unRegister(mContext);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ final SwitchPreference switchPreference = (SwitchPreference) preference;
+ final boolean videoCallEnabled = isVideoCallEnabled();
+ switchPreference.setVisible(videoCallEnabled);
+ if (videoCallEnabled) {
+ final boolean is4gLteEnabled = mImsManager.isEnhanced4gLteModeSettingEnabledByUser()
+ && mImsManager.isNonTtyOrTtyOnVolteEnabled();
+ preference.setEnabled(is4gLteEnabled &&
+ mTelephonyManager.getCallState(mSubId) == TelephonyManager.CALL_STATE_IDLE);
+ switchPreference.setChecked(is4gLteEnabled && mImsManager.isVtEnabledByUser());
+ }
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ mImsManager.setVtSetting(isChecked);
+ return true;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mImsManager.isVtEnabledByUser();
+ }
+
+ public VideoCallingPreferenceController init(int subId) {
+ mSubId = subId;
+ mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
+ if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
+ }
+
+ return this;
+ }
+
+ @VisibleForTesting
+ boolean isVideoCallEnabled() {
+ return mCarrierConfig != null && mImsManager != null
+ && mImsManager.isVtEnabledByPlatform()
+ && mImsManager.isVtProvisionedOnDevice()
+ && MobileNetworkUtils.isImsServiceStateReady(mImsManager)
+ && (mCarrierConfig.getBoolean(
+ CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
+ || mTelephonyManager.isDataEnabled());
+ }
+
+ @Override
+ public void on4gLteUpdated() {
+ updateState(mPreference);
+ }
+
+ private class PhoneCallStateListener extends PhoneStateListener {
+
+ public PhoneCallStateListener(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ updateState(mPreference);
+ }
+
+ public void register(int subId) {
+ mSubId = subId;
+ mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
+ }
+
+ public void unregister() {
+ mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
+ }
+ }
+
+ /**
+ * Listener that listens mobile data state change.
+ */
+ public class DataContentObserver extends ContentObserver {
+
+ public DataContentObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ updateState(mPreference);
+ }
+
+ public void register(Context context, int subId) {
+ Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
+ if (TelephonyManager.getDefault().getSimCount() != 1) {
+ uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
+ }
+ context.getContentResolver().registerContentObserver(uri,
+ false /* notifyForDescendants */, this /* observer */);
+ }
+
+ public void unRegister(Context context) {
+ context.getContentResolver().unregisterContentObserver(this);
+ }
+ }
+}
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
new file mode 100644
index 00000000000..09bf2d72ca2
--- /dev/null
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Looper;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+import java.util.List;
+
+/**
+ * Preference controller for "Wifi Calling"
+ */
+public class WifiCallingPreferenceController extends BasePreferenceController implements
+ LifecycleObserver, OnStart, OnStop {
+
+ private TelephonyManager mTelephonyManager;
+ @VisibleForTesting
+ ImsManager mImsManager;
+ @VisibleForTesting
+ PhoneAccountHandle mSimCallManager;
+ private PhoneCallStateListener mPhoneStateListener;
+ private Preference mPreference;
+ private int mSubId;
+
+ public WifiCallingPreferenceController(Context context, String key) {
+ super(context, key);
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
+ mSimCallManager = context.getSystemService(TelecomManager.class).getSimCallManager();
+ mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
+ mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ && MobileNetworkUtils.isWifiCallingEnabled(mContext,
+ SubscriptionManager.getPhoneId(mSubId))
+ ? AVAILABLE
+ : CONDITIONALLY_UNAVAILABLE;
+ }
+
+ @Override
+ public void onStart() {
+ mPhoneStateListener.register(mSubId);
+ }
+
+ @Override
+ public void onStop() {
+ mPhoneStateListener.unregister();
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mSimCallManager != null) {
+ Intent intent = MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext,
+ mSimCallManager);
+ final PackageManager pm = mContext.getPackageManager();
+ List resolutions = pm.queryIntentActivities(intent, 0);
+ preference.setTitle(resolutions.get(0).loadLabel(pm));
+ preference.setSummary(null);
+ preference.setIntent(intent);
+ } else {
+ int resId = com.android.internal.R.string.wifi_calling_off_summary;
+ if (mImsManager.isWfcEnabledByUser()) {
+ final boolean isRoaming = mTelephonyManager.isNetworkRoaming();
+ int wfcMode = mImsManager.getWfcMode(isRoaming);
+
+ switch (wfcMode) {
+ case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY:
+ resId = com.android.internal.R.string.wfc_mode_wifi_only_summary;
+ break;
+ case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED:
+ resId = com.android.internal.R.string
+ .wfc_mode_cellular_preferred_summary;
+ break;
+ case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED:
+ resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary;
+ break;
+ default:
+ break;
+ }
+ }
+ preference.setSummary(resId);
+ }
+ preference.setEnabled(
+ mTelephonyManager.getCallState(mSubId) == TelephonyManager.CALL_STATE_IDLE);
+ }
+
+ public void init(int subId) {
+ mSubId = subId;
+ mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
+ mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
+ }
+
+ private class PhoneCallStateListener extends PhoneStateListener {
+
+ public PhoneCallStateListener(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ updateState(mPreference);
+ }
+
+ public void register(int subId) {
+ mSubId = subId;
+ mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE);
+ }
+
+ public void unregister() {
+ mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java
new file mode 100644
index 00000000000..e50e2646e5a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.telephony.ims.feature.ImsFeature;
+
+import androidx.preference.SwitchPreference;
+
+import com.android.ims.ImsManager;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class VideoCallingPreferenceControllerTest {
+ private static final int SUB_ID = 2;
+
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private ImsManager mImsManager;
+ @Mock
+ private CarrierConfigManager mCarrierConfigManager;
+
+ private VideoCallingPreferenceController mController;
+ private PersistableBundle mCarrierConfig;
+ private SwitchPreference mPreference;
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+ doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class);
+ doReturn(mCarrierConfigManager).when(mContext).getSystemService(CarrierConfigManager.class);
+ doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+
+ mCarrierConfig = new PersistableBundle();
+ mCarrierConfig.putBoolean(
+ CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
+ doReturn(mCarrierConfig).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
+
+ mPreference = new SwitchPreference(mContext);
+ mController = new VideoCallingPreferenceController(mContext, "wifi_calling");
+ mController.init(SUB_ID);
+ mController.mImsManager = mImsManager;
+ mPreference.setKey(mController.getPreferenceKey());
+
+ doReturn(true).when(mImsManager).isVtEnabledByPlatform();
+ doReturn(true).when(mImsManager).isVtProvisionedOnDevice();
+ doReturn(ImsFeature.STATE_READY).when(mImsManager).getImsServiceState();
+ doReturn(true).when(mTelephonyManager).isDataEnabled();
+ }
+
+ @Test
+ public void isVideoCallEnabled_allFlagsOn_returnTrue() {
+ assertThat(mController.isVideoCallEnabled()).isTrue();
+ }
+
+ @Test
+ public void isVideoCallEnabled_disabledByPlatform_returnFalse() {
+ doReturn(false).when(mImsManager).isVtEnabledByPlatform();
+
+ assertThat(mController.isVideoCallEnabled()).isFalse();
+ }
+
+ @Test
+ public void isVideoCallEnabled_dataDisabled_returnFalse() {
+ mCarrierConfig.putBoolean(
+ CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, false);
+ doReturn(false).when(mTelephonyManager).isDataEnabled();
+
+ assertThat(mController.isVideoCallEnabled()).isFalse();
+ }
+
+ @Test
+ public void updateState_4gLteOff_disabled() {
+ doReturn(false).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser();
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isFalse();
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void updateState_4gLteOnWithoutCall_checked() {
+ doReturn(true).when(mImsManager).isVtEnabledByUser();
+ doReturn(true).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser();
+ doReturn(true).when(mImsManager).isNonTtyOrTtyOnVolteEnabled();
+ doReturn(TelephonyManager.CALL_STATE_IDLE).when(mTelephonyManager).getCallState(SUB_ID);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isTrue();
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java
new file mode 100644
index 00000000000..35297bd8d58
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.Preference;
+
+import com.android.ims.ImsConfig;
+import com.android.ims.ImsManager;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class WifiCallingPreferenceControllerTest {
+ private static final int SUB_ID = 2;
+
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private ImsManager mImsManager;
+
+ private WifiCallingPreferenceController mController;
+ private Preference mPreference;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+ doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+
+ mPreference = new Preference(mContext);
+ mController = new WifiCallingPreferenceController(mContext, "wifi_calling");
+ mController.init(SUB_ID);
+ mController.mImsManager = mImsManager;
+ mPreference.setKey(mController.getPreferenceKey());
+ }
+
+ @Test
+ public void updateState_noSimCallManager_setCorrectSummary() {
+ mController.mSimCallManager = null;
+ doReturn(true).when(mImsManager).isWfcEnabledByUser();
+ doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY).when(mImsManager).getWfcMode(
+ anyBoolean());
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary()).isEqualTo(
+ mContext.getString(com.android.internal.R.string.wfc_mode_wifi_only_summary));
+ }
+
+ @Test
+ public void updateState_notCallIdle_disable() {
+ doReturn(TelephonyManager.CALL_STATE_RINGING).when(mTelephonyManager).getCallState(SUB_ID);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isEnabled()).isFalse();
+ }
+
+}