Refactor wifi calling and video calling

Also add a Callback for 4gLte to notify update to video calling
preference controller

Bug: 114749736
Test: RunSettingsRoboTests
Change-Id: I0b5009733251162327f02ccfae8b10ae56b961bc
This commit is contained in:
jackqdyulei
2018-10-19 11:25:15 -07:00
parent f3fb639f49
commit 3d7e38bc57
7 changed files with 610 additions and 235 deletions

View File

@@ -82,20 +82,20 @@
<PreferenceScreen <PreferenceScreen
android:key="wifi_calling_key" android:key="wifi_calling_key"
android:title="@string/wifi_calling_settings_title"> android:title="@string/wifi_calling_settings_title"
settings:controller="com.android.settings.network.telephony.WifiCallingPreferenceController" >
<intent android:action="android.intent.action.MAIN" <intent android:action="android.intent.action.MAIN"
android:targetPackage="com.android.settings" android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.Settings$WifiCallingSettingsActivity"> android:targetClass="com.android.settings.Settings$WifiCallingSettingsActivity">
<extra android:name="show_drawer_menu" android:value="true" /> <extra android:name="show_drawer_menu" android:value="true" />
</intent> </intent>
</PreferenceScreen> </PreferenceScreen>
<SwitchPreference <SwitchPreference
android:key="video_calling_key" android:key="video_calling_key"
android:title="@string/video_calling_settings_title" android:title="@string/video_calling_settings_title"
android:persistent="true"/> android:persistent="true"
settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController" />
</PreferenceCategory> </PreferenceCategory>

View File

@@ -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.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.ArrayList;
import java.util.List;
/** /**
* Preference controller for "Enhanced 4G LTE" * Preference controller for "Enhanced 4G LTE"
*/ */
@@ -49,11 +52,13 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle
@VisibleForTesting @VisibleForTesting
ImsManager mImsManager; ImsManager mImsManager;
private PhoneCallStateListener mPhoneStateListener; private PhoneCallStateListener mPhoneStateListener;
private final List<On4gLteUpdateListener> m4gLteListeners;
private int mSubId; private int mSubId;
public Enhanced4gLtePreferenceController(Context context, String key) { public Enhanced4gLtePreferenceController(Context context, String key) {
super(context, key); super(context, key);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
m4gLteListeners = new ArrayList<>();
mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper()); mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper());
mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
} }
@@ -105,6 +110,9 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle
@Override @Override
public boolean setChecked(boolean isChecked) { public boolean setChecked(boolean isChecked) {
mImsManager.setEnhanced4gLteModeSetting(isChecked); mImsManager.setEnhanced4gLteModeSetting(isChecked);
for (final On4gLteUpdateListener lsn : m4gLteListeners) {
lsn.on4gLteUpdated();
}
return true; return true;
} }
@@ -113,13 +121,20 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle
return mImsManager.isEnhanced4gLteModeSettingEnabledByUser(); return mImsManager.isEnhanced4gLteModeSettingEnabledByUser();
} }
public void init(int subId) { public Enhanced4gLtePreferenceController init(int subId) {
mSubId = subId; mSubId = subId;
mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId);
mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId)); mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId));
} }
return this;
}
public Enhanced4gLtePreferenceController addListener(On4gLteUpdateListener lsn) {
m4gLteListeners.add(lsn);
return this;
} }
private boolean is4gLtePrefEnabled() { private boolean is4gLtePrefEnabled() {
@@ -151,4 +166,11 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle
mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
} }
} }
/**
* Update other preferences when 4gLte state is changed
*/
public interface On4gLteUpdateListener {
void on4gLteUpdated();
}
} }

View File

@@ -26,22 +26,17 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.SearchIndexableResource; import android.provider.SearchIndexableResource;
import android.telecom.PhoneAccountHandle; import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager; import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState; import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.MenuItem; import android.view.MenuItem;
@@ -51,9 +46,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.ims.ImsConfig;
import com.android.ims.ImsManager; import com.android.ims.ImsManager;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto; 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_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key";
private static final String BUTTON_CARRIER_SETTINGS_EUICC_KEY = private static final String BUTTON_CARRIER_SETTINGS_EUICC_KEY =
"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_MOBILE_DATA_ENABLE_KEY = "mobile_data_enable";
private static final String BUTTON_DATA_USAGE_KEY = "data_usage_summary"; private static final String BUTTON_DATA_USAGE_KEY = "data_usage_summary";
private static final String BUTTON_ADVANCED_OPTIONS_KEY = "advanced_options"; private static final String BUTTON_ADVANCED_OPTIONS_KEY = "advanced_options";
@@ -120,13 +111,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
private CarrierConfigManager mCarrierConfigManager; private CarrierConfigManager mCarrierConfigManager;
private int mSubId; private int mSubId;
//UI objects
private SwitchPreference mButton4glte;
private PreferenceCategory mCallingCategory;
private Preference mWiFiCallingPref;
private SwitchPreference mVideoCallingPref;
private NetworkSelectListPreference mButtonNetworkSelect;
private CdmaSystemSelectPreferenceController mCdmaSystemSelectPreferenceController; private CdmaSystemSelectPreferenceController mCdmaSystemSelectPreferenceController;
private CdmaSubscriptionPreferenceController mCdmaSubscriptionPreferenceController; private CdmaSubscriptionPreferenceController mCdmaSubscriptionPreferenceController;
@@ -147,44 +131,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
private boolean mOnlyAutoSelectInHomeNW; private boolean mOnlyAutoSelectInHomeNW;
private boolean mUnavailable; 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 @Override
public int getMetricsCategory() { public int getMetricsCategory() {
//TODO(b/114749736): add metrics id for it //TODO(b/114749736): add metrics id for it
@@ -221,11 +167,9 @@ public class MobileNetworkFragment extends DashboardFragment implements
REQUEST_CODE_EXIT_ECM); REQUEST_CODE_EXIT_ECM);
} }
return true; return true;
} else if (preference == mWiFiCallingPref || preference == mVideoCallingPref) {
return false;
} }
return true; return false;
} }
private final SubscriptionManager.OnSubscriptionsChangedListener private final SubscriptionManager.OnSubscriptionsChangedListener
@@ -255,8 +199,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
SubscriptionManager.getPhoneId(mSubId)); SubscriptionManager.getPhoneId(mSubId));
mTelephonyManager = new TelephonyManager(getContext(), mSubId); mTelephonyManager = new TelephonyManager(getContext(), mSubId);
} }
mPhoneStateListener.updateSubscriptionId(mSubId);
} }
@Override @Override
@@ -272,14 +214,19 @@ public class MobileNetworkFragment extends DashboardFragment implements
use(DataUsagePreferenceController.class).init(mSubId); use(DataUsagePreferenceController.class).init(mSubId);
use(PreferredNetworkModePreferenceController.class).init(mSubId); use(PreferredNetworkModePreferenceController.class).init(mSubId);
use(EnabledNetworkModePreferenceController.class).init(mSubId); use(EnabledNetworkModePreferenceController.class).init(mSubId);
use(Enhanced4gLtePreferenceController.class).init(mSubId);
use(DataServiceSetupPreferenceController.class).init(mSubId); use(DataServiceSetupPreferenceController.class).init(mSubId);
use(EuiccPreferenceController.class).init(mSubId); use(EuiccPreferenceController.class).init(mSubId);
use(WifiCallingPreferenceController.class).init(mSubId);
mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class); mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class);
mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId); mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId);
mCdmaSubscriptionPreferenceController = use(CdmaSubscriptionPreferenceController.class); mCdmaSubscriptionPreferenceController = use(CdmaSubscriptionPreferenceController.class);
mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId); mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId);
final VideoCallingPreferenceController videoCallingPreferenceController =
use(VideoCallingPreferenceController.class).init(mSubId);
use(Enhanced4gLtePreferenceController.class).init(mSubId)
.addListener(videoCallingPreferenceController);
} }
@Override @Override
@@ -299,12 +246,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
Context.TELEPHONY_SERVICE); Context.TELEPHONY_SERVICE);
mCarrierConfigManager = new CarrierConfigManager(getContext()); 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 { try {
Context con = context.createPackageContext("com.android.systemui", 0); Context con = context.createPackageContext("com.android.systemui", 0);
int id = con.getResources().getIdentifier("config_show4GForLTE", int id = con.getResources().getIdentifier("config_show4GForLTE",
@@ -378,11 +319,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
// preferences. // preferences.
getPreferenceScreen().setEnabled(true); getPreferenceScreen().setEnabled(true);
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
// Video calling and WiFi calling state might have changed.
updateCallingCategory();
mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener); mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
final Context context = getContext(); 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.getString(activity.getContentResolver(),
android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL)); android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL));
updatePreferredNetworkType();
updateCallingCategory();
// Enable link to CMAS app settings depending on the value in config.xml. // Enable link to CMAS app settings depending on the value in config.xml.
final boolean isCellBroadcastAppLinkEnabled = activity.getResources().getBoolean( final boolean isCellBroadcastAppLinkEnabled = activity.getResources().getBoolean(
com.android.internal.R.bool.config_cellBroadcastAppLinks); com.android.internal.R.bool.config_cellBroadcastAppLinks);
@@ -555,8 +488,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
super.onPause(); super.onPause();
if (DBG) log("onPause:+"); if (DBG) log("onPause:+");
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
mSubscriptionManager mSubscriptionManager
.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener); .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
@@ -576,18 +507,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
*/ */
public boolean onPreferenceChange(Preference preference, Object objValue) { public boolean onPreferenceChange(Preference preference, Object objValue) {
sendMetricsEventPreferenceChanged(getPreferenceScreen(), preference, 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(); updateBody();
// always let the preference setting proceed. // 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<ResolveInfo> 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) { private static void log(String msg) {
Log.d(LOG_TAG, 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 // 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 // open the list dialog. When a value is chosen, another MetricsEvent is logged with
// new value in onPreferenceChange. // new value in onPreferenceChange.
if (preference == mWiFiCallingPref if (preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
|| preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
|| preference == preferenceScreen.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY) || preference == preferenceScreen.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)
|| preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY) || preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY)
|| preference == preferenceScreen.findPreference(BUTTON_CDMA_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. // MetricsEvent logging with new value, for SwitchPreferences and ListPreferences.
if (preference == mVideoCallingPref) { if (preference == preferenceScreen
MetricsLogger.action(getContext(), category, (Boolean) newValue);
} else if (preference == preferenceScreen
.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY) .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY)
|| preference == preferenceScreen || preference == preferenceScreen
.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) { .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) {
@@ -888,10 +699,6 @@ public class MobileNetworkFragment extends DashboardFragment implements
if (preference == null) { if (preference == null) {
return MetricsProto.MetricsEvent.VIEW_UNKNOWN; 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 } else if (preference == preferenceScreen
.findPreference(NetworkOperators.BUTTON_AUTO_SELECT_KEY)) { .findPreference(NetworkOperators.BUTTON_AUTO_SELECT_KEY)) {
return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE; return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE;
@@ -995,31 +802,4 @@ public class MobileNetworkFragment extends DashboardFragment implements
return result; return result;
} }
}; };
private static final class SetPreferredNetworkAsyncTask extends AsyncTask<Void, Void, Boolean> {
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();
}
}
} }

View File

@@ -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);
}
}
}

View File

@@ -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<ResolveInfo> 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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}