MSIM support for Wi-Fi calling setting.
UI change to support Wi-Fi calling settings for multi-SIM devices. Bug: b/65648147 Test: manual Change-Id: Ia2e3a835400873bf6d8bfc7a7690d98e74049076
This commit is contained in:
45
res/layout/wifi_calling_settings_preferences.xml
Normal file
45
res/layout/wifi_calling_settings_preferences.xml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2014 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/tabs_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.android.settings.widget.SwitchBar
|
||||||
|
android:id="@+id/switch_bar"
|
||||||
|
android:layout_height="?android:attr/actionBarSize"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:background="@drawable/switchbar_background"
|
||||||
|
android:theme="?attr/switchBarTheme" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@android:id/tabcontent"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="0dip" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/prefs_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dip"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clipChildren="false"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:smoothScrollbar="false" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
36
res/layout/wifi_calling_settings_tabs.xml
Normal file
36
res/layout/wifi_calling_settings_tabs.xml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2017 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/tabs_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.android.settings.widget.SlidingTabLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/sliding_tabs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="none"
|
||||||
|
android:fillViewport="true"/>
|
||||||
|
|
||||||
|
<com.android.settings.widget.RtlCompatibleViewPager
|
||||||
|
android:id="@+id/view_pager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@@ -16,190 +16,38 @@
|
|||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Fragment;
|
||||||
import android.app.AlertDialog;
|
import android.app.FragmentManager;
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.PersistableBundle;
|
import android.support.v13.app.FragmentPagerAdapter;
|
||||||
import android.support.v7.preference.ListPreference;
|
import android.telephony.SubscriptionInfo;
|
||||||
import android.support.v7.preference.Preference;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
|
||||||
import android.support.v7.preference.PreferenceScreen;
|
|
||||||
import android.telephony.CarrierConfigManager;
|
|
||||||
import android.telephony.PhoneStateListener;
|
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Switch;
|
import android.view.LayoutInflater;
|
||||||
import android.widget.TextView;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.android.ims.ImsConfig;
|
import com.android.ims.ImsConfig;
|
||||||
import com.android.ims.ImsManager;
|
import com.android.ims.ImsManager;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.internal.telephony.Phone;
|
import com.android.settings.widget.RtlCompatibleViewPager;
|
||||||
import com.android.settings.widget.SwitchBar;
|
import com.android.settings.widget.SlidingTabLayout;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Wi-Fi Calling settings" screen. This preference screen lets you
|
* "Wi-Fi Calling settings" screen. This is the container fragment which holds
|
||||||
* enable/disable Wi-Fi Calling and change Wi-Fi Calling mode.
|
* {@link WifiCallingSettingsForSub} fragments.
|
||||||
*/
|
*/
|
||||||
public class WifiCallingSettings extends SettingsPreferenceFragment
|
public class WifiCallingSettings extends SettingsPreferenceFragment {
|
||||||
implements SwitchBar.OnSwitchChangeListener,
|
|
||||||
Preference.OnPreferenceChangeListener {
|
|
||||||
|
|
||||||
private static final String TAG = "WifiCallingSettings";
|
private static final String TAG = "WifiCallingSettings";
|
||||||
|
private List<SubscriptionInfo> mSil;
|
||||||
//String keys for preference lookup
|
|
||||||
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
|
|
||||||
private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
|
|
||||||
private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
|
|
||||||
|
|
||||||
private static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
|
|
||||||
|
|
||||||
public static final String EXTRA_LAUNCH_CARRIER_APP = "EXTRA_LAUNCH_CARRIER_APP";
|
|
||||||
|
|
||||||
public static final int LAUCH_APP_ACTIVATE = 0;
|
|
||||||
public static final int LAUCH_APP_UPDATE = 1;
|
|
||||||
|
|
||||||
//UI objects
|
//UI objects
|
||||||
private SwitchBar mSwitchBar;
|
private RtlCompatibleViewPager mViewPager;
|
||||||
private Switch mSwitch;
|
private WifiCallingViewPagerAdapter mPagerAdapter;
|
||||||
private ListPreference mButtonWfcMode;
|
private SlidingTabLayout mTabLayout;
|
||||||
private ListPreference mButtonWfcRoamingMode;
|
|
||||||
private Preference mUpdateAddress;
|
|
||||||
private TextView mEmptyView;
|
|
||||||
|
|
||||||
private boolean mValidListener = false;
|
|
||||||
private boolean mEditableWfcMode = true;
|
|
||||||
private boolean mEditableWfcRoamingMode = true;
|
|
||||||
|
|
||||||
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
|
|
||||||
/*
|
|
||||||
* Enable/disable controls 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) {
|
|
||||||
final SettingsActivity activity = (SettingsActivity) getActivity();
|
|
||||||
boolean isNonTtyOrTtyOnVolteEnabled = ImsManager
|
|
||||||
.isNonTtyOrTtyOnVolteEnabled(activity);
|
|
||||||
final SwitchBar switchBar = activity.getSwitchBar();
|
|
||||||
boolean isWfcEnabled = switchBar.getSwitch().isChecked()
|
|
||||||
&& isNonTtyOrTtyOnVolteEnabled;
|
|
||||||
|
|
||||||
switchBar.setEnabled((state == TelephonyManager.CALL_STATE_IDLE)
|
|
||||||
&& isNonTtyOrTtyOnVolteEnabled);
|
|
||||||
|
|
||||||
boolean isWfcModeEditable = true;
|
|
||||||
boolean isWfcRoamingModeEditable = false;
|
|
||||||
final CarrierConfigManager configManager = (CarrierConfigManager)
|
|
||||||
activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
|
|
||||||
if (configManager != null) {
|
|
||||||
PersistableBundle b = configManager.getConfig();
|
|
||||||
if (b != null) {
|
|
||||||
isWfcModeEditable = b.getBoolean(
|
|
||||||
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
|
|
||||||
isWfcRoamingModeEditable = b.getBoolean(
|
|
||||||
CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
|
|
||||||
if (pref != null) {
|
|
||||||
pref.setEnabled(isWfcEnabled && isWfcModeEditable
|
|
||||||
&& (state == TelephonyManager.CALL_STATE_IDLE));
|
|
||||||
}
|
|
||||||
Preference pref_roam = getPreferenceScreen().findPreference(BUTTON_WFC_ROAMING_MODE);
|
|
||||||
if (pref_roam != null) {
|
|
||||||
pref_roam.setEnabled(isWfcEnabled && isWfcRoamingModeEditable
|
|
||||||
&& (state == TelephonyManager.CALL_STATE_IDLE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final OnPreferenceClickListener mUpdateAddressListener =
|
|
||||||
new OnPreferenceClickListener() {
|
|
||||||
/*
|
|
||||||
* Launch carrier emergency address managemnent activity
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
|
||||||
final Context context = getActivity();
|
|
||||||
Intent carrierAppIntent = getCarrierActivityIntent(context);
|
|
||||||
if (carrierAppIntent != null) {
|
|
||||||
carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
|
|
||||||
startActivity(carrierAppIntent);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
|
||||||
super.onActivityCreated(savedInstanceState);
|
|
||||||
|
|
||||||
final SettingsActivity activity = (SettingsActivity) getActivity();
|
|
||||||
|
|
||||||
mSwitchBar = activity.getSwitchBar();
|
|
||||||
mSwitch = mSwitchBar.getSwitch();
|
|
||||||
mSwitchBar.show();
|
|
||||||
|
|
||||||
mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
|
|
||||||
setEmptyView(mEmptyView);
|
|
||||||
String emptyViewText = activity.getString(R.string.wifi_calling_off_explanation)
|
|
||||||
+ activity.getString(R.string.wifi_calling_off_explanation_2);
|
|
||||||
mEmptyView.setText(emptyViewText);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
mSwitchBar.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showAlert(Intent intent) {
|
|
||||||
Context context = getActivity();
|
|
||||||
|
|
||||||
CharSequence title = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_TITLE);
|
|
||||||
CharSequence message = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_MESSAGE);
|
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
|
||||||
builder.setMessage(message)
|
|
||||||
.setTitle(title)
|
|
||||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
|
||||||
.setPositiveButton(android.R.string.ok, null);
|
|
||||||
AlertDialog dialog = builder.create();
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private IntentFilter mIntentFilter;
|
|
||||||
|
|
||||||
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
String action = intent.getAction();
|
|
||||||
if (action.equals(ImsManager.ACTION_IMS_REGISTRATION_ERROR)) {
|
|
||||||
// If this fragment is active then we are immediately
|
|
||||||
// showing alert on screen. There is no need to add
|
|
||||||
// notification in this case.
|
|
||||||
//
|
|
||||||
// In order to communicate to ImsPhone that it should
|
|
||||||
// not show notification, we are changing result code here.
|
|
||||||
setResultCode(Activity.RESULT_CANCELED);
|
|
||||||
|
|
||||||
// UX requirement is to disable WFC in case of "permanent" registration failures.
|
|
||||||
mSwitch.setChecked(false);
|
|
||||||
|
|
||||||
showAlert(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMetricsCategory() {
|
public int getMetricsCategory() {
|
||||||
@@ -207,242 +55,81 @@ public class WifiCallingSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
super.onCreate(savedInstanceState);
|
Bundle savedInstanceState) {
|
||||||
|
final View view = inflater.inflate(R.layout.wifi_calling_settings_tabs, container, false);
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.wifi_calling_settings);
|
mTabLayout = view.findViewById(R.id.sliding_tabs);
|
||||||
|
mViewPager = (RtlCompatibleViewPager) view.findViewById(R.id.view_pager);
|
||||||
|
|
||||||
mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
|
mPagerAdapter = new WifiCallingViewPagerAdapter(getChildFragmentManager(), mViewPager);
|
||||||
mButtonWfcMode.setOnPreferenceChangeListener(this);
|
mViewPager.setAdapter(mPagerAdapter);
|
||||||
|
|
||||||
mButtonWfcRoamingMode = (ListPreference) findPreference(BUTTON_WFC_ROAMING_MODE);
|
return view;
|
||||||
mButtonWfcRoamingMode.setOnPreferenceChangeListener(this);
|
|
||||||
|
|
||||||
mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS);
|
|
||||||
mUpdateAddress.setOnPreferenceClickListener(mUpdateAddressListener);
|
|
||||||
|
|
||||||
mIntentFilter = new IntentFilter();
|
|
||||||
mIntentFilter.addAction(ImsManager.ACTION_IMS_REGISTRATION_ERROR);
|
|
||||||
|
|
||||||
CarrierConfigManager configManager = (CarrierConfigManager)
|
|
||||||
getSystemService(Context.CARRIER_CONFIG_SERVICE);
|
|
||||||
boolean isWifiOnlySupported = true;
|
|
||||||
if (configManager != null) {
|
|
||||||
PersistableBundle b = configManager.getConfig();
|
|
||||||
if (b != null) {
|
|
||||||
mEditableWfcMode = b.getBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
|
|
||||||
mEditableWfcRoamingMode = b.getBoolean(
|
|
||||||
CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
|
|
||||||
isWifiOnlySupported = b.getBoolean(
|
|
||||||
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isWifiOnlySupported) {
|
|
||||||
mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only);
|
|
||||||
mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only);
|
|
||||||
mButtonWfcRoamingMode.setEntries(
|
|
||||||
R.array.wifi_calling_mode_choices_v2_without_wifi_only);
|
|
||||||
mButtonWfcRoamingMode.setEntryValues(
|
|
||||||
R.array.wifi_calling_mode_values_without_wifi_only);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onResume();
|
super.onCreate(icicle);
|
||||||
|
// TODO: besides in onCreate, we should also update subList when SIM / Sub status
|
||||||
final Context context = getActivity();
|
// changes.
|
||||||
|
updateSubList();
|
||||||
// NOTE: Buttons will be enabled/disabled in mPhoneStateListener
|
|
||||||
boolean wfcEnabled = ImsManager.isWfcEnabledByUser(context)
|
|
||||||
&& ImsManager.isNonTtyOrTtyOnVolteEnabled(context);
|
|
||||||
mSwitch.setChecked(wfcEnabled);
|
|
||||||
int wfcMode = ImsManager.getWfcMode(context, false);
|
|
||||||
int wfcRoamingMode = ImsManager.getWfcMode(context, true);
|
|
||||||
mButtonWfcMode.setValue(Integer.toString(wfcMode));
|
|
||||||
mButtonWfcRoamingMode.setValue(Integer.toString(wfcRoamingMode));
|
|
||||||
updateButtonWfcMode(context, wfcEnabled, wfcMode, wfcRoamingMode);
|
|
||||||
|
|
||||||
if (ImsManager.isWfcEnabledByPlatform(context)) {
|
|
||||||
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
|
|
||||||
tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
|
||||||
|
|
||||||
mSwitchBar.addOnSwitchChangeListener(this);
|
|
||||||
|
|
||||||
mValidListener = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.registerReceiver(mIntentReceiver, mIntentFilter);
|
|
||||||
|
|
||||||
Intent intent = getActivity().getIntent();
|
|
||||||
if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) {
|
|
||||||
showAlert(intent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onStart() {
|
||||||
super.onPause();
|
super.onStart();
|
||||||
|
|
||||||
final Context context = getActivity();
|
if (mSil != null && mSil.size() > 1) {
|
||||||
|
mTabLayout.setViewPager(mViewPager);
|
||||||
if (mValidListener) {
|
|
||||||
mValidListener = false;
|
|
||||||
|
|
||||||
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
|
|
||||||
tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
|
|
||||||
|
|
||||||
mSwitchBar.removeOnSwitchChangeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.unregisterReceiver(mIntentReceiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listens to the state change of the switch.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
|
||||||
final Context context = getActivity();
|
|
||||||
Log.d(TAG, "onSwitchChanged(" + isChecked + ")");
|
|
||||||
|
|
||||||
if (!isChecked) {
|
|
||||||
updateWfcMode(context, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call address management activity before turning on WFC
|
|
||||||
Intent carrierAppIntent = getCarrierActivityIntent(context);
|
|
||||||
if (carrierAppIntent != null) {
|
|
||||||
carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
|
|
||||||
startActivityForResult(carrierAppIntent, REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
|
|
||||||
} else {
|
} else {
|
||||||
updateWfcMode(context, true);
|
mTabLayout.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
private final class WifiCallingViewPagerAdapter extends FragmentPagerAdapter {
|
||||||
* Get the Intent to launch carrier emergency address management activity.
|
private final RtlCompatibleViewPager mViewPager;
|
||||||
* Return null when no activity found.
|
|
||||||
*/
|
|
||||||
private static Intent getCarrierActivityIntent(Context context) {
|
|
||||||
// Retrive component name from carrirt config
|
|
||||||
CarrierConfigManager configManager = context.getSystemService(CarrierConfigManager.class);
|
|
||||||
if (configManager == null) return null;
|
|
||||||
|
|
||||||
PersistableBundle bundle = configManager.getConfig();
|
public WifiCallingViewPagerAdapter(FragmentManager fragmentManager,
|
||||||
if (bundle == null) return null;
|
RtlCompatibleViewPager viewPager) {
|
||||||
|
super(fragmentManager);
|
||||||
String carrierApp = bundle.getString(
|
mViewPager = viewPager;
|
||||||
CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING);
|
|
||||||
if (TextUtils.isEmpty(carrierApp)) return null;
|
|
||||||
|
|
||||||
ComponentName componentName = ComponentName.unflattenFromString(carrierApp);
|
|
||||||
if (componentName == null) return null;
|
|
||||||
|
|
||||||
// Build and return intent
|
|
||||||
Intent intent = new Intent();
|
|
||||||
intent.setComponent(componentName);
|
|
||||||
return intent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Turn on/off WFC mode with ImsManager and update UI accordingly
|
|
||||||
*/
|
|
||||||
private void updateWfcMode(Context context, boolean wfcEnabled) {
|
|
||||||
Log.i(TAG, "updateWfcMode(" + wfcEnabled + ")");
|
|
||||||
ImsManager.setWfcSetting(context, wfcEnabled);
|
|
||||||
|
|
||||||
int wfcMode = ImsManager.getWfcMode(context, false);
|
|
||||||
int wfcRoamingMode = ImsManager.getWfcMode(context, true);
|
|
||||||
updateButtonWfcMode(context, wfcEnabled, wfcMode, wfcRoamingMode);
|
|
||||||
if (wfcEnabled) {
|
|
||||||
mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), wfcMode);
|
|
||||||
} else {
|
|
||||||
mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), -1);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public CharSequence getPageTitle(int position) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
return String.valueOf(mSil.get(position).getDisplayName());
|
||||||
|
|
||||||
final Context context = getActivity();
|
|
||||||
|
|
||||||
if (requestCode == REQUEST_CHECK_WFC_EMERGENCY_ADDRESS) {
|
|
||||||
Log.d(TAG, "WFC emergency address activity result = " + resultCode);
|
|
||||||
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
updateWfcMode(context, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void updateButtonWfcMode(Context context, boolean wfcEnabled,
|
@Override
|
||||||
int wfcMode, int wfcRoamingMode) {
|
public Fragment getItem(int position) {
|
||||||
mButtonWfcMode.setSummary(getWfcModeSummary(context, wfcMode));
|
Log.d(TAG, "Adapter getItem " + position);
|
||||||
mButtonWfcMode.setEnabled(wfcEnabled && mEditableWfcMode);
|
final Bundle args = new Bundle();
|
||||||
// mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
|
args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID,
|
||||||
mButtonWfcRoamingMode.setEnabled(wfcEnabled && mEditableWfcRoamingMode);
|
mSil.get(position).getSubscriptionId());
|
||||||
|
WifiCallingSettingsForSub fragment = new WifiCallingSettingsForSub();
|
||||||
|
fragment.setArguments(args);
|
||||||
|
|
||||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
return fragment;
|
||||||
boolean updateAddressEnabled = (getCarrierActivityIntent(context) != null);
|
}
|
||||||
if (wfcEnabled) {
|
|
||||||
if (mEditableWfcMode) {
|
@Override
|
||||||
preferenceScreen.addPreference(mButtonWfcMode);
|
public Object instantiateItem(ViewGroup container, int position) {
|
||||||
|
Log.d(TAG, "Adapter instantiateItem " + position);
|
||||||
|
return super.instantiateItem(container,
|
||||||
|
mViewPager.getRtlAwareIndex(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
if (mSil == null) {
|
||||||
|
Log.d(TAG, "Adapter getCount null mSil ");
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
// Don't show WFC (home) preference if it's not editable.
|
Log.d(TAG, "Adapter getCount " + mSil.size());
|
||||||
preferenceScreen.removePreference(mButtonWfcMode);
|
return mSil.size();
|
||||||
}
|
|
||||||
if (mEditableWfcRoamingMode) {
|
|
||||||
preferenceScreen.addPreference(mButtonWfcRoamingMode);
|
|
||||||
} else {
|
|
||||||
// Don't show WFC roaming preference if it's not editable.
|
|
||||||
preferenceScreen.removePreference(mButtonWfcRoamingMode);
|
|
||||||
}
|
|
||||||
if (updateAddressEnabled) {
|
|
||||||
preferenceScreen.addPreference(mUpdateAddress);
|
|
||||||
} else {
|
|
||||||
preferenceScreen.removePreference(mUpdateAddress);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
preferenceScreen.removePreference(mButtonWfcMode);
|
|
||||||
preferenceScreen.removePreference(mButtonWfcRoamingMode);
|
|
||||||
preferenceScreen.removePreference(mUpdateAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
final Context context = getActivity();
|
|
||||||
if (preference == mButtonWfcMode) {
|
|
||||||
mButtonWfcMode.setValue((String) newValue);
|
|
||||||
int buttonMode = Integer.valueOf((String) newValue);
|
|
||||||
int currentWfcMode = ImsManager.getWfcMode(context, false);
|
|
||||||
if (buttonMode != currentWfcMode) {
|
|
||||||
ImsManager.setWfcMode(context, buttonMode, false);
|
|
||||||
mButtonWfcMode.setSummary(getWfcModeSummary(context, buttonMode));
|
|
||||||
mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
|
|
||||||
}
|
|
||||||
if (!mEditableWfcRoamingMode) {
|
|
||||||
int currentWfcRoamingMode = ImsManager.getWfcMode(context, true);
|
|
||||||
if (buttonMode != currentWfcRoamingMode) {
|
|
||||||
ImsManager.setWfcMode(context, buttonMode, true);
|
|
||||||
// mButtonWfcRoamingMode.setSummary is not needed; summary is selected value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (preference == mButtonWfcRoamingMode) {
|
|
||||||
mButtonWfcRoamingMode.setValue((String) newValue);
|
|
||||||
int buttonMode = Integer.valueOf((String) newValue);
|
|
||||||
int currentMode = ImsManager.getWfcMode(context, true);
|
|
||||||
if (buttonMode != currentMode) {
|
|
||||||
ImsManager.setWfcMode(context, buttonMode, true);
|
|
||||||
// mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
|
|
||||||
mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getWfcModeSummary(Context context, int wfcMode) {
|
public static int getWfcModeSummary(Context context, int wfcMode) {
|
||||||
@@ -464,4 +151,22 @@ public class WifiCallingSettings extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
return resId;
|
return resId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateSubList() {
|
||||||
|
mSil = SubscriptionManager.from(getActivity()).getActiveSubscriptionInfoList();
|
||||||
|
|
||||||
|
// Only config Wfc if it's enabled by platform.
|
||||||
|
if (mSil == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < mSil.size();) {
|
||||||
|
ImsManager imsManager = ImsManager.getInstance(getActivity(),
|
||||||
|
mSil.get(i).getSimSlotIndex());
|
||||||
|
if (!imsManager.isWfcEnabledByPlatform()) {
|
||||||
|
mSil.remove(i);
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
521
src/com/android/settings/WifiCallingSettingsForSub.java
Normal file
521
src/com/android/settings/WifiCallingSettingsForSub.java
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.PersistableBundle;
|
||||||
|
import android.support.v7.preference.ListPreference;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
||||||
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
|
import android.telephony.CarrierConfigManager;
|
||||||
|
import android.telephony.PhoneStateListener;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Switch;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.android.ims.ImsConfig;
|
||||||
|
import com.android.ims.ImsManager;
|
||||||
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
|
import com.android.internal.telephony.Phone;
|
||||||
|
import com.android.settings.widget.SwitchBar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the inner class of {@link WifiCallingSettings} fragment.
|
||||||
|
* The preference screen lets you enable/disable Wi-Fi Calling and change Wi-Fi Calling mode.
|
||||||
|
*/
|
||||||
|
public class WifiCallingSettingsForSub extends SettingsPreferenceFragment
|
||||||
|
implements SwitchBar.OnSwitchChangeListener,
|
||||||
|
Preference.OnPreferenceChangeListener {
|
||||||
|
private static final String TAG = "WifiCallingSettingsForSub";
|
||||||
|
|
||||||
|
//String keys for preference lookup
|
||||||
|
private static final String BUTTON_WFC_MODE = "wifi_calling_mode";
|
||||||
|
private static final String BUTTON_WFC_ROAMING_MODE = "wifi_calling_roaming_mode";
|
||||||
|
private static final String PREFERENCE_EMERGENCY_ADDRESS = "emergency_address_key";
|
||||||
|
|
||||||
|
private static final int REQUEST_CHECK_WFC_EMERGENCY_ADDRESS = 1;
|
||||||
|
|
||||||
|
public static final String EXTRA_LAUNCH_CARRIER_APP = "EXTRA_LAUNCH_CARRIER_APP";
|
||||||
|
|
||||||
|
protected static final String FRAGMENT_BUNDLE_SUBID = "subId";
|
||||||
|
|
||||||
|
public static final int LAUCH_APP_ACTIVATE = 0;
|
||||||
|
public static final int LAUCH_APP_UPDATE = 1;
|
||||||
|
|
||||||
|
//UI objects
|
||||||
|
private SwitchBar mSwitchBar;
|
||||||
|
private Switch mSwitch;
|
||||||
|
private ListPreference mButtonWfcMode;
|
||||||
|
private ListPreference mButtonWfcRoamingMode;
|
||||||
|
private Preference mUpdateAddress;
|
||||||
|
private TextView mEmptyView;
|
||||||
|
|
||||||
|
private boolean mValidListener = false;
|
||||||
|
private boolean mEditableWfcMode = true;
|
||||||
|
private boolean mEditableWfcRoamingMode = true;
|
||||||
|
|
||||||
|
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
|
private ImsManager mImsManager;
|
||||||
|
|
||||||
|
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
|
||||||
|
/*
|
||||||
|
* Enable/disable controls 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) {
|
||||||
|
final SettingsActivity activity = (SettingsActivity) getActivity();
|
||||||
|
boolean isNonTtyOrTtyOnVolteEnabled = mImsManager.isNonTtyOrTtyOnVolteEnabled();
|
||||||
|
boolean isWfcEnabled = mSwitchBar.isChecked()
|
||||||
|
&& isNonTtyOrTtyOnVolteEnabled;
|
||||||
|
|
||||||
|
mSwitchBar.setEnabled((state == TelephonyManager.CALL_STATE_IDLE)
|
||||||
|
&& isNonTtyOrTtyOnVolteEnabled);
|
||||||
|
|
||||||
|
boolean isWfcModeEditable = true;
|
||||||
|
boolean isWfcRoamingModeEditable = false;
|
||||||
|
final CarrierConfigManager configManager = (CarrierConfigManager)
|
||||||
|
activity.getSystemService(Context.CARRIER_CONFIG_SERVICE);
|
||||||
|
if (configManager != null) {
|
||||||
|
PersistableBundle b = configManager.getConfigForSubId(mSubId);
|
||||||
|
if (b != null) {
|
||||||
|
isWfcModeEditable = b.getBoolean(
|
||||||
|
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
|
||||||
|
isWfcRoamingModeEditable = b.getBoolean(
|
||||||
|
CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Preference pref = getPreferenceScreen().findPreference(BUTTON_WFC_MODE);
|
||||||
|
if (pref != null) {
|
||||||
|
pref.setEnabled(isWfcEnabled && isWfcModeEditable
|
||||||
|
&& (state == TelephonyManager.CALL_STATE_IDLE));
|
||||||
|
}
|
||||||
|
Preference pref_roam =
|
||||||
|
getPreferenceScreen().findPreference(BUTTON_WFC_ROAMING_MODE);
|
||||||
|
if (pref_roam != null) {
|
||||||
|
pref_roam.setEnabled(isWfcEnabled && isWfcRoamingModeEditable
|
||||||
|
&& (state == TelephonyManager.CALL_STATE_IDLE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getHelpResource() {
|
||||||
|
// Helper resource is already defined in the container fragment.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final OnPreferenceClickListener mUpdateAddressListener =
|
||||||
|
new OnPreferenceClickListener() {
|
||||||
|
/*
|
||||||
|
* Launch carrier emergency address managemnent activity
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
Intent carrierAppIntent = getCarrierActivityIntent();
|
||||||
|
if (carrierAppIntent != null) {
|
||||||
|
carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_UPDATE);
|
||||||
|
startActivity(carrierAppIntent);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
|
super.onActivityCreated(savedInstanceState);
|
||||||
|
|
||||||
|
final SettingsActivity activity = (SettingsActivity) getActivity();
|
||||||
|
|
||||||
|
mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
|
||||||
|
setEmptyView(mEmptyView);
|
||||||
|
String emptyViewText = activity.getString(R.string.wifi_calling_off_explanation)
|
||||||
|
+ activity.getString(R.string.wifi_calling_off_explanation_2);
|
||||||
|
mEmptyView.setText(emptyViewText);
|
||||||
|
|
||||||
|
mSwitchBar = getView().findViewById(R.id.switch_bar);
|
||||||
|
mSwitchBar.show();
|
||||||
|
mSwitch = mSwitchBar.getSwitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
mSwitchBar.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAlert(Intent intent) {
|
||||||
|
Context context = getActivity();
|
||||||
|
|
||||||
|
CharSequence title = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_TITLE);
|
||||||
|
CharSequence message = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_MESSAGE);
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
builder.setMessage(message)
|
||||||
|
.setTitle(title)
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setPositiveButton(android.R.string.ok, null);
|
||||||
|
AlertDialog dialog = builder.create();
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntentFilter mIntentFilter;
|
||||||
|
|
||||||
|
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String action = intent.getAction();
|
||||||
|
if (action.equals(ImsManager.ACTION_IMS_REGISTRATION_ERROR)) {
|
||||||
|
// If this fragment is active then we are immediately
|
||||||
|
// showing alert on screen. There is no need to add
|
||||||
|
// notification in this case.
|
||||||
|
//
|
||||||
|
// In order to communicate to ImsPhone that it should
|
||||||
|
// not show notification, we are changing result code here.
|
||||||
|
setResultCode(Activity.RESULT_CANCELED);
|
||||||
|
|
||||||
|
// UX requirement is to disable WFC in case of "permanent" registration failures.
|
||||||
|
mSwitch.setChecked(false);
|
||||||
|
|
||||||
|
showAlert(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMetricsCategory() {
|
||||||
|
return MetricsEvent.WIFI_CALLING_FOR_SUB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
addPreferencesFromResource(R.xml.wifi_calling_settings);
|
||||||
|
|
||||||
|
// SubId should always be specified when creating this fragment. Either through
|
||||||
|
// fragment.setArguments() or through savedInstanceState.
|
||||||
|
if (getArguments() != null && getArguments().containsKey(FRAGMENT_BUNDLE_SUBID))
|
||||||
|
{
|
||||||
|
mSubId = getArguments().getInt(FRAGMENT_BUNDLE_SUBID);
|
||||||
|
} else if (savedInstanceState != null) {
|
||||||
|
mSubId = savedInstanceState.getInt(
|
||||||
|
FRAGMENT_BUNDLE_SUBID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
mImsManager = ImsManager.getInstance(
|
||||||
|
getActivity(), SubscriptionManager.getPhoneId(mSubId));
|
||||||
|
|
||||||
|
mButtonWfcMode = (ListPreference) findPreference(BUTTON_WFC_MODE);
|
||||||
|
mButtonWfcMode.setOnPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
mButtonWfcRoamingMode = (ListPreference) findPreference(BUTTON_WFC_ROAMING_MODE);
|
||||||
|
mButtonWfcRoamingMode.setOnPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
mUpdateAddress = (Preference) findPreference(PREFERENCE_EMERGENCY_ADDRESS);
|
||||||
|
mUpdateAddress.setOnPreferenceClickListener(mUpdateAddressListener);
|
||||||
|
|
||||||
|
mIntentFilter = new IntentFilter();
|
||||||
|
mIntentFilter.addAction(ImsManager.ACTION_IMS_REGISTRATION_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
outState.putInt(FRAGMENT_BUNDLE_SUBID, mSubId);
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
View view = inflater.inflate(
|
||||||
|
R.layout.wifi_calling_settings_preferences, container, false);
|
||||||
|
|
||||||
|
final ViewGroup prefs_container = view.findViewById(R.id.prefs_container);
|
||||||
|
Utils.prepareCustomPreferencesList(container, view, prefs_container, false);
|
||||||
|
View prefs = super.onCreateView(inflater, prefs_container, savedInstanceState);
|
||||||
|
prefs_container.addView(prefs);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBody() {
|
||||||
|
CarrierConfigManager configManager = (CarrierConfigManager)
|
||||||
|
getSystemService(Context.CARRIER_CONFIG_SERVICE);
|
||||||
|
boolean isWifiOnlySupported = true;
|
||||||
|
|
||||||
|
if (configManager != null) {
|
||||||
|
PersistableBundle b = configManager.getConfigForSubId(mSubId);
|
||||||
|
if (b != null) {
|
||||||
|
mEditableWfcMode = b.getBoolean(
|
||||||
|
CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL);
|
||||||
|
mEditableWfcRoamingMode = b.getBoolean(
|
||||||
|
CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL);
|
||||||
|
isWifiOnlySupported = b.getBoolean(
|
||||||
|
CarrierConfigManager.KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isWifiOnlySupported) {
|
||||||
|
mButtonWfcMode.setEntries(R.array.wifi_calling_mode_choices_without_wifi_only);
|
||||||
|
mButtonWfcMode.setEntryValues(R.array.wifi_calling_mode_values_without_wifi_only);
|
||||||
|
mButtonWfcRoamingMode.setEntries(
|
||||||
|
R.array.wifi_calling_mode_choices_v2_without_wifi_only);
|
||||||
|
mButtonWfcRoamingMode.setEntryValues(
|
||||||
|
R.array.wifi_calling_mode_values_without_wifi_only);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: Buttons will be enabled/disabled in mPhoneStateListener
|
||||||
|
boolean wfcEnabled = mImsManager.isWfcEnabledByUser()
|
||||||
|
&& mImsManager.isNonTtyOrTtyOnVolteEnabled();
|
||||||
|
mSwitch.setChecked(wfcEnabled);
|
||||||
|
int wfcMode = mImsManager.getWfcMode(false);
|
||||||
|
int wfcRoamingMode = mImsManager.getWfcMode(true);
|
||||||
|
mButtonWfcMode.setValue(Integer.toString(wfcMode));
|
||||||
|
mButtonWfcRoamingMode.setValue(Integer.toString(wfcRoamingMode));
|
||||||
|
updateButtonWfcMode(wfcEnabled, wfcMode, wfcRoamingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
|
||||||
|
final Context context = getActivity();
|
||||||
|
|
||||||
|
updateBody();
|
||||||
|
|
||||||
|
if (mImsManager.isWfcEnabledByPlatform()) {
|
||||||
|
TelephonyManager tm =
|
||||||
|
(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
|
tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
||||||
|
|
||||||
|
mSwitchBar.addOnSwitchChangeListener(this);
|
||||||
|
|
||||||
|
mValidListener = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.registerReceiver(mIntentReceiver, mIntentFilter);
|
||||||
|
|
||||||
|
Intent intent = getActivity().getIntent();
|
||||||
|
if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) {
|
||||||
|
showAlert(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
|
||||||
|
final Context context = getActivity();
|
||||||
|
|
||||||
|
if (mValidListener) {
|
||||||
|
mValidListener = false;
|
||||||
|
|
||||||
|
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
|
tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||||
|
|
||||||
|
mSwitchBar.removeOnSwitchChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.unregisterReceiver(mIntentReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens to the state change of the switch.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
||||||
|
Log.d(TAG, "onSwitchChanged(" + isChecked + ")");
|
||||||
|
|
||||||
|
if (!isChecked) {
|
||||||
|
updateWfcMode(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call address management activity before turning on WFC
|
||||||
|
Intent carrierAppIntent = getCarrierActivityIntent();
|
||||||
|
if (carrierAppIntent != null) {
|
||||||
|
carrierAppIntent.putExtra(EXTRA_LAUNCH_CARRIER_APP, LAUCH_APP_ACTIVATE);
|
||||||
|
startActivityForResult(carrierAppIntent, REQUEST_CHECK_WFC_EMERGENCY_ADDRESS);
|
||||||
|
} else {
|
||||||
|
updateWfcMode(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the Intent to launch carrier emergency address management activity.
|
||||||
|
* Return null when no activity found.
|
||||||
|
*/
|
||||||
|
private Intent getCarrierActivityIntent() {
|
||||||
|
// Retrive component name from carrier config
|
||||||
|
CarrierConfigManager configManager =
|
||||||
|
getActivity().getSystemService(CarrierConfigManager.class);
|
||||||
|
if (configManager == null) return null;
|
||||||
|
|
||||||
|
PersistableBundle bundle = configManager.getConfigForSubId(mSubId);
|
||||||
|
if (bundle == null) return null;
|
||||||
|
|
||||||
|
String carrierApp = bundle.getString(
|
||||||
|
CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING);
|
||||||
|
if (TextUtils.isEmpty(carrierApp)) return null;
|
||||||
|
|
||||||
|
ComponentName componentName = ComponentName.unflattenFromString(carrierApp);
|
||||||
|
if (componentName == null) return null;
|
||||||
|
|
||||||
|
// Build and return intent
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setComponent(componentName);
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Turn on/off WFC mode with ImsManager and update UI accordingly
|
||||||
|
*/
|
||||||
|
private void updateWfcMode(boolean wfcEnabled) {
|
||||||
|
Log.i(TAG, "updateWfcMode(" + wfcEnabled + ")");
|
||||||
|
mImsManager.setWfcSetting(wfcEnabled);
|
||||||
|
|
||||||
|
int wfcMode = mImsManager.getWfcMode(false);
|
||||||
|
int wfcRoamingMode = mImsManager.getWfcMode(true);
|
||||||
|
updateButtonWfcMode(wfcEnabled, wfcMode, wfcRoamingMode);
|
||||||
|
if (wfcEnabled) {
|
||||||
|
mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), wfcMode);
|
||||||
|
} else {
|
||||||
|
mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
|
final Context context = getActivity();
|
||||||
|
|
||||||
|
if (requestCode == REQUEST_CHECK_WFC_EMERGENCY_ADDRESS) {
|
||||||
|
Log.d(TAG, "WFC emergency address activity result = " + resultCode);
|
||||||
|
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
updateWfcMode(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateButtonWfcMode(boolean wfcEnabled,
|
||||||
|
int wfcMode, int wfcRoamingMode) {
|
||||||
|
mButtonWfcMode.setSummary(getWfcModeSummary(wfcMode));
|
||||||
|
mButtonWfcMode.setEnabled(wfcEnabled && mEditableWfcMode);
|
||||||
|
// mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
|
||||||
|
mButtonWfcRoamingMode.setEnabled(wfcEnabled && mEditableWfcRoamingMode);
|
||||||
|
|
||||||
|
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||||
|
boolean updateAddressEnabled = (getCarrierActivityIntent() != null);
|
||||||
|
if (wfcEnabled) {
|
||||||
|
if (mEditableWfcMode) {
|
||||||
|
preferenceScreen.addPreference(mButtonWfcMode);
|
||||||
|
} else {
|
||||||
|
// Don't show WFC (home) preference if it's not editable.
|
||||||
|
preferenceScreen.removePreference(mButtonWfcMode);
|
||||||
|
}
|
||||||
|
if (mEditableWfcRoamingMode) {
|
||||||
|
preferenceScreen.addPreference(mButtonWfcRoamingMode);
|
||||||
|
} else {
|
||||||
|
// Don't show WFC roaming preference if it's not editable.
|
||||||
|
preferenceScreen.removePreference(mButtonWfcRoamingMode);
|
||||||
|
}
|
||||||
|
if (updateAddressEnabled) {
|
||||||
|
preferenceScreen.addPreference(mUpdateAddress);
|
||||||
|
} else {
|
||||||
|
preferenceScreen.removePreference(mUpdateAddress);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
preferenceScreen.removePreference(mButtonWfcMode);
|
||||||
|
preferenceScreen.removePreference(mButtonWfcRoamingMode);
|
||||||
|
preferenceScreen.removePreference(mUpdateAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
|
if (preference == mButtonWfcMode) {
|
||||||
|
Log.d(TAG, "onPreferenceChange mButtonWfcMode " + newValue);
|
||||||
|
mButtonWfcMode.setValue((String) newValue);
|
||||||
|
int buttonMode = Integer.valueOf((String) newValue);
|
||||||
|
int currentWfcMode = mImsManager.getWfcMode(false);
|
||||||
|
if (buttonMode != currentWfcMode) {
|
||||||
|
mImsManager.setWfcMode(buttonMode, false);
|
||||||
|
mButtonWfcMode.setSummary(getWfcModeSummary(buttonMode));
|
||||||
|
mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
|
||||||
|
}
|
||||||
|
if (!mEditableWfcRoamingMode) {
|
||||||
|
int currentWfcRoamingMode = mImsManager.getWfcMode(true);
|
||||||
|
if (buttonMode != currentWfcRoamingMode) {
|
||||||
|
mImsManager.setWfcMode(buttonMode, true);
|
||||||
|
// mButtonWfcRoamingMode.setSummary is not needed; summary is selected value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (preference == mButtonWfcRoamingMode) {
|
||||||
|
mButtonWfcRoamingMode.setValue((String) newValue);
|
||||||
|
int buttonMode = Integer.valueOf((String) newValue);
|
||||||
|
int currentMode = mImsManager.getWfcMode(true);
|
||||||
|
if (buttonMode != currentMode) {
|
||||||
|
mImsManager.setWfcMode(buttonMode, true);
|
||||||
|
// mButtonWfcRoamingMode.setSummary is not needed; summary is just selected value.
|
||||||
|
mMetricsFeatureProvider.action(getActivity(), getMetricsCategory(), buttonMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getWfcModeSummary(int wfcMode) {
|
||||||
|
int resId = com.android.internal.R.string.wifi_calling_off_summary;
|
||||||
|
if (mImsManager.isWfcEnabledByUser()) {
|
||||||
|
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:
|
||||||
|
Log.e(TAG, "Unexpected WFC mode value: " + wfcMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resId;
|
||||||
|
}
|
||||||
|
}
|
@@ -79,6 +79,7 @@ com.android.settings.ApnSettings
|
|||||||
com.android.settings.SecuritySettings$SecuritySubSettings
|
com.android.settings.SecuritySettings$SecuritySubSettings
|
||||||
com.android.settings.PrivacySettings
|
com.android.settings.PrivacySettings
|
||||||
com.android.settings.WifiCallingSettings
|
com.android.settings.WifiCallingSettings
|
||||||
|
com.android.settings.WifiCallingSettingsForSub
|
||||||
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
|
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
|
||||||
com.android.settings.SetupRedactionInterstitial$SetupRedactionInterstitialFragment
|
com.android.settings.SetupRedactionInterstitial$SetupRedactionInterstitialFragment
|
||||||
com.android.settings.TrustAgentSettings
|
com.android.settings.TrustAgentSettings
|
||||||
|
@@ -5,7 +5,7 @@ include $(CLEAR_VARS)
|
|||||||
LOCAL_MODULE_TAGS := tests
|
LOCAL_MODULE_TAGS := tests
|
||||||
LOCAL_CERTIFICATE := platform
|
LOCAL_CERTIFICATE := platform
|
||||||
|
|
||||||
LOCAL_JAVA_LIBRARIES := android.test.runner
|
LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common ims-common
|
||||||
|
|
||||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||||
android-support-test \
|
android-support-test \
|
||||||
|
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 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.testutils;
|
||||||
|
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
// This class is for replacing existing system service with the mocked service.
|
||||||
|
// Copied from CellBroadcastReceiver app.
|
||||||
|
public final class MockedServiceManager {
|
||||||
|
|
||||||
|
private final String TAG = MockedServiceManager.class.getSimpleName();
|
||||||
|
|
||||||
|
private final HashMap<String, IBinder> mServiceManagerMockedServices = new HashMap<>();
|
||||||
|
|
||||||
|
private final HashMap<InstanceKey, Object> mOldInstances = new HashMap<>();
|
||||||
|
|
||||||
|
private final LinkedList<InstanceKey> mInstanceKeys = new LinkedList<>();
|
||||||
|
|
||||||
|
private static class InstanceKey {
|
||||||
|
final Class mClass;
|
||||||
|
final String mInstName;
|
||||||
|
final Object mObj;
|
||||||
|
|
||||||
|
InstanceKey(final Class c, final String instName, final Object obj) {
|
||||||
|
mClass = c;
|
||||||
|
mInstName = instName;
|
||||||
|
mObj = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null || obj.getClass() != getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstanceKey other = (InstanceKey) obj;
|
||||||
|
return (other.mClass == mClass && other.mInstName.equals(mInstName)
|
||||||
|
&& other.mObj == mObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MockedServiceManager() throws Exception {
|
||||||
|
replaceInstance(ServiceManager.class, "sCache", null, mServiceManagerMockedServices);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceService(String key, IBinder binder) {
|
||||||
|
mServiceManagerMockedServices.put(key, binder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restoreAllServices() throws Exception {
|
||||||
|
restoreInstances();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void replaceInstance(final Class c, final String instanceName,
|
||||||
|
final Object obj, final Object newValue)
|
||||||
|
throws Exception {
|
||||||
|
Field field = c.getDeclaredField(instanceName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
|
||||||
|
InstanceKey key = new InstanceKey(c, instanceName, obj);
|
||||||
|
if (!mOldInstances.containsKey(key)) {
|
||||||
|
mOldInstances.put(key, field.get(obj));
|
||||||
|
mInstanceKeys.add(key);
|
||||||
|
}
|
||||||
|
field.set(obj, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void restoreInstances() throws Exception {
|
||||||
|
Iterator<InstanceKey> it = mInstanceKeys.descendingIterator();
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
InstanceKey key = it.next();
|
||||||
|
Field field = key.mClass.getDeclaredField(key.mInstName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(key.mObj, mOldInstances.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
mInstanceKeys.clear();
|
||||||
|
mOldInstances.clear();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,299 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2017 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.wifi;
|
||||||
|
|
||||||
|
import static android.support.test.espresso.Espresso.onView;
|
||||||
|
import static android.support.test.espresso.action.ViewActions.click;
|
||||||
|
import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
|
||||||
|
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||||
|
import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
|
||||||
|
import static android.support.test.espresso.matcher.ViewMatchers.isSelected;
|
||||||
|
import static android.support.test.espresso.matcher.ViewMatchers.withResourceName;
|
||||||
|
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.allOf;
|
||||||
|
import static org.hamcrest.CoreMatchers.anything;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.matchers.JUnitMatchers.containsString;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.support.test.InstrumentationRegistry;
|
||||||
|
import android.support.test.espresso.NoMatchingViewException;
|
||||||
|
import android.support.test.espresso.ViewInteraction;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
import android.support.test.uiautomator.UiDevice;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
|
|
||||||
|
import com.android.ims.ImsConfig;
|
||||||
|
import com.android.ims.ImsManager;
|
||||||
|
import com.android.internal.telephony.SubscriptionController;
|
||||||
|
import com.android.settings.testutils.MockedServiceManager;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class WifiCallingSettingUiTest {
|
||||||
|
private static final String SUBSCRIPTION0_NAME = "SUB0";
|
||||||
|
private static final String SUBSCRIPTION1_NAME = "SUB1";
|
||||||
|
private static final String WFC_MODE_TITLE = "Calling preference";
|
||||||
|
private static final String WFC_MODE_WIFI_ONLY = "Wi-Fi only";
|
||||||
|
private static final String WFC_MODE_WIFI_PREFERRED = "Wi-Fi preferred";
|
||||||
|
private static final String WFC_MODE_CELLULAR_PREFERRED = "Mobile preferred";
|
||||||
|
|
||||||
|
private Instrumentation mInstrumentation;
|
||||||
|
private Context mContext;
|
||||||
|
private UiDevice mDevice;
|
||||||
|
@Mock
|
||||||
|
SubscriptionController mSubscriptionController;
|
||||||
|
MockedServiceManager mMockedServiceManager;
|
||||||
|
protected HashMap<Integer, ImsManager> mImsManagerInstances = new HashMap<>();
|
||||||
|
List<SubscriptionInfo> mSils = new ArrayList();
|
||||||
|
@Mock
|
||||||
|
SubscriptionInfo mSubscriptionInfo0;
|
||||||
|
@Mock
|
||||||
|
SubscriptionInfo mSubscriptionInfo1;
|
||||||
|
@Mock
|
||||||
|
ImsManager mImsManager0;
|
||||||
|
@Mock
|
||||||
|
ImsManager mImsManager1;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
mContext = mInstrumentation.getTargetContext();
|
||||||
|
mDevice = UiDevice.getInstance(mInstrumentation);
|
||||||
|
|
||||||
|
mMockedServiceManager = new MockedServiceManager();
|
||||||
|
mMockedServiceManager.replaceService("isub", mSubscriptionController);
|
||||||
|
|
||||||
|
mMockedServiceManager.replaceInstance(
|
||||||
|
ImsManager.class, "sImsManagerInstances", null, mImsManagerInstances);
|
||||||
|
mMockedServiceManager.replaceInstance(
|
||||||
|
SubscriptionController.class, "sInstance", null, mSubscriptionController);
|
||||||
|
doReturn(mSubscriptionController)
|
||||||
|
.when(mSubscriptionController).queryLocalInterface(anyString());
|
||||||
|
mImsManagerInstances.put(0, mImsManager0);
|
||||||
|
mImsManagerInstances.put(1, mImsManager1);
|
||||||
|
doReturn(mSils).when(mSubscriptionController).getActiveSubscriptionInfoList(anyString());
|
||||||
|
doReturn(0).when(mSubscriptionController).getPhoneId(0);
|
||||||
|
doReturn(1).when(mSubscriptionController).getPhoneId(1);
|
||||||
|
doReturn(0).when(mSubscriptionInfo0).getSubscriptionId();
|
||||||
|
doReturn(1).when(mSubscriptionInfo1).getSubscriptionId();
|
||||||
|
doReturn(0).when(mSubscriptionInfo0).getSimSlotIndex();
|
||||||
|
doReturn(1).when(mSubscriptionInfo1).getSimSlotIndex();
|
||||||
|
doReturn(SUBSCRIPTION0_NAME).when(mSubscriptionInfo0).getDisplayName();
|
||||||
|
doReturn(SUBSCRIPTION1_NAME).when(mSubscriptionInfo1).getDisplayName();
|
||||||
|
|
||||||
|
doReturn(true).when(mImsManager0).isWfcEnabledByPlatform();
|
||||||
|
doReturn(true).when(mImsManager0).isNonTtyOrTtyOnVolteEnabled();
|
||||||
|
doReturn(true).when(mImsManager1).isWfcEnabledByPlatform();
|
||||||
|
doReturn(true).when(mImsManager1).isNonTtyOrTtyOnVolteEnabled();
|
||||||
|
|
||||||
|
mDevice.wakeUp();
|
||||||
|
mDevice.pressMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
mMockedServiceManager.restoreAllServices();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleSimUi() throws InterruptedException {
|
||||||
|
configureSingleSim();
|
||||||
|
doReturn(true).when(mImsManager0).isWfcEnabledByUser();
|
||||||
|
doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
|
||||||
|
.when(mImsManager0).getWfcMode();
|
||||||
|
doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
|
||||||
|
.when(mImsManager0).getWfcMode(anyBoolean());
|
||||||
|
|
||||||
|
mInstrumentation.startActivitySync(createActivityIntent());
|
||||||
|
|
||||||
|
checkSingleSimUi();
|
||||||
|
|
||||||
|
try {
|
||||||
|
mDevice.setOrientationLeft();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Assert.fail("Exception " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-check after rotation. Fragment should be recreated properly.
|
||||||
|
checkSingleSimUi();
|
||||||
|
|
||||||
|
try {
|
||||||
|
mDevice.setOrientationNatural();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Assert.fail("Exception " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-check after rotation. Fragment should be resumed properly.
|
||||||
|
checkSingleSimUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSingleSimUi() {
|
||||||
|
assertEquals(false, checkExists(onView(withText(SUBSCRIPTION0_NAME))));
|
||||||
|
assertEquals(false, checkExists(onView(withText(SUBSCRIPTION1_NAME))));
|
||||||
|
assertEquals(true, checkExists(onView(withText(WFC_MODE_TITLE))));
|
||||||
|
assertEquals(true, checkExists(onView(withText(WFC_MODE_WIFI_PREFERRED))));
|
||||||
|
checkSwitchBarStatus(true, true);
|
||||||
|
checkEmptyViewStatus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoValidSub() throws InterruptedException {
|
||||||
|
configureDualSim();
|
||||||
|
doReturn(false).when(mImsManager0).isWfcEnabledByPlatform();
|
||||||
|
doReturn(false).when(mImsManager0).isNonTtyOrTtyOnVolteEnabled();
|
||||||
|
doReturn(false).when(mImsManager1).isWfcEnabledByPlatform();
|
||||||
|
doReturn(false).when(mImsManager1).isNonTtyOrTtyOnVolteEnabled();
|
||||||
|
doReturn(false).when(mImsManager0).isWfcEnabledByUser();
|
||||||
|
doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
|
||||||
|
.when(mImsManager0).getWfcMode();
|
||||||
|
doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
|
||||||
|
.when(mImsManager0).getWfcMode(anyBoolean());
|
||||||
|
|
||||||
|
Activity activity = mInstrumentation.startActivitySync(createActivityIntent());
|
||||||
|
|
||||||
|
assertEquals(false, checkExists(onView(withText(SUBSCRIPTION0_NAME))));
|
||||||
|
assertEquals(false, checkExists(onView(withText(SUBSCRIPTION1_NAME))));
|
||||||
|
assertEquals(false, checkExists(onView(withText(WFC_MODE_TITLE))));
|
||||||
|
|
||||||
|
checkSwitchBarStatus(false, false);
|
||||||
|
checkEmptyViewStatus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWfcDisabled() throws InterruptedException {
|
||||||
|
configureSingleSim();
|
||||||
|
doReturn(false).when(mImsManager0).isWfcEnabledByUser();
|
||||||
|
doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
|
||||||
|
.when(mImsManager0).getWfcMode();
|
||||||
|
doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED)
|
||||||
|
.when(mImsManager0).getWfcMode(anyBoolean());
|
||||||
|
|
||||||
|
Activity activity = mInstrumentation.startActivitySync(createActivityIntent());
|
||||||
|
|
||||||
|
assertEquals(false, checkExists(onView(withText(SUBSCRIPTION0_NAME))));
|
||||||
|
assertEquals(false, checkExists(onView(withText(SUBSCRIPTION1_NAME))));
|
||||||
|
assertEquals(false, checkExists(onView(withText(WFC_MODE_TITLE))));
|
||||||
|
|
||||||
|
checkSwitchBarStatus(true, false);
|
||||||
|
checkEmptyViewStatus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDualSimUi() throws InterruptedException {
|
||||||
|
configureDualSim();
|
||||||
|
doReturn(true).when(mImsManager0).isWfcEnabledByUser();
|
||||||
|
doReturn(false).when(mImsManager1).isWfcEnabledByUser();
|
||||||
|
doReturn(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED)
|
||||||
|
.when(mImsManager0).getWfcMode();
|
||||||
|
doReturn(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED)
|
||||||
|
.when(mImsManager0).getWfcMode(anyBoolean());
|
||||||
|
|
||||||
|
mInstrumentation.startActivitySync(createActivityIntent());
|
||||||
|
|
||||||
|
assertEquals(true, checkExists(onView(withText(SUBSCRIPTION0_NAME))));
|
||||||
|
assertEquals(true, checkExists(onView(withText(SUBSCRIPTION1_NAME))));
|
||||||
|
assertEquals(true, checkExists(onView(withText(WFC_MODE_TITLE))));
|
||||||
|
assertEquals(true, checkExists(onView(withText(WFC_MODE_CELLULAR_PREFERRED))));
|
||||||
|
|
||||||
|
onView(withText(SUBSCRIPTION0_NAME)).check(matches(isSelected()));
|
||||||
|
checkSwitchBarStatus(true, true);
|
||||||
|
checkEmptyViewStatus(false);
|
||||||
|
|
||||||
|
// Switch to SUB1.
|
||||||
|
onView(withText(SUBSCRIPTION1_NAME)).perform(click());
|
||||||
|
|
||||||
|
checkSwitchBarStatus(true, false);
|
||||||
|
checkEmptyViewStatus(true);
|
||||||
|
onView(withText(SUBSCRIPTION1_NAME)).check(matches(isSelected()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkExists(ViewInteraction v) {
|
||||||
|
try {
|
||||||
|
v.check(matches(isCompletelyDisplayed()));
|
||||||
|
return true;
|
||||||
|
} catch (NoMatchingViewException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Intent createActivityIntent() {
|
||||||
|
Intent intent = new Intent(mContext,
|
||||||
|
com.android.settings.Settings.WifiCallingSettingsActivity.class);
|
||||||
|
intent.setPackage("com.android.settings");
|
||||||
|
intent.setAction("android.intent.action.MAIN");
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureSingleSim() {
|
||||||
|
mSils.clear();
|
||||||
|
mSils.add(mSubscriptionInfo0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureDualSim() {
|
||||||
|
mSils.clear();
|
||||||
|
mSils.add(mSubscriptionInfo0);
|
||||||
|
mSils.add(mSubscriptionInfo1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSwitchBarStatus(boolean shouldDisplay, boolean statusOn) {
|
||||||
|
if (shouldDisplay) {
|
||||||
|
try {
|
||||||
|
onView(allOf(withResourceName("switch_text"), isCompletelyDisplayed()))
|
||||||
|
.check(matches(withText(containsString(statusOn ? "On" : "Off"))));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Assert.fail("Exception " + e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onView(allOf(withResourceName("switch_text"), isCompletelyDisplayed()))
|
||||||
|
.check(doesNotExist());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkEmptyViewStatus(boolean shouldDisplay) {
|
||||||
|
try {
|
||||||
|
if (!shouldDisplay) {
|
||||||
|
onView(allOf(withResourceName("empty"), isCompletelyDisplayed()))
|
||||||
|
.check(doesNotExist());
|
||||||
|
} else {
|
||||||
|
onView(allOf(withResourceName("empty"), isCompletelyDisplayed()))
|
||||||
|
.check(matches(anything()));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Assert.fail("Exception " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user