diff --git a/res/xml/network_setting_fragment.xml b/res/xml/network_setting_fragment.xml index e54a90d7730..43cadab7671 100644 --- a/res/xml/network_setting_fragment.xml +++ b/res/xml/network_setting_fragment.xml @@ -73,7 +73,8 @@ + android:title="@string/carrier_settings_euicc" + settings:controller="com.android.settings.network.telephony.EuiccPreferenceController" /> - + android:title="@string/wifi_calling_settings_title" + settings:controller="com.android.settings.network.telephony.WifiCallingPreferenceController" > - + android:persistent="true" + settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController" /> diff --git a/src/com/android/settings/homepage/ContextualCardManager.java b/src/com/android/settings/homepage/ContextualCardManager.java index 87b048ea959..6acf7b1ade3 100644 --- a/src/com/android/settings/homepage/ContextualCardManager.java +++ b/src/com/android/settings/homepage/ContextualCardManager.java @@ -115,10 +115,6 @@ public class ContextualCardManager implements CardContentLoader.CardContentLoade @Override public void onContextualCardUpdated(Map> updateList) { - //TODO(b/112245748): Should implement a DiffCallback. - //Keep the old list for comparison. - final List prevCards = mContextualCards; - final Set cardTypes = updateList.keySet(); //Remove the existing data that matches the certain cardType before inserting new data. final List cardsToKeep = mContextualCards diff --git a/src/com/android/settings/homepage/ContextualCardsAdapter.java b/src/com/android/settings/homepage/ContextualCardsAdapter.java index 81cae39bde8..8e6f805c9f8 100644 --- a/src/com/android/settings/homepage/ContextualCardsAdapter.java +++ b/src/com/android/settings/homepage/ContextualCardsAdapter.java @@ -17,11 +17,13 @@ package com.android.settings.homepage; import android.content.Context; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.lifecycle.LifecycleOwner; +import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -108,14 +110,15 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter> cards) { final List contextualCards = cards.get(ContextualCard.CardType.DEFAULT); - //TODO(b/112245748): Should implement a DiffCallback so we can use notifyItemChanged() - // instead. if (contextualCards == null) { mContextualCards.clear(); + notifyDataSetChanged(); } else { + final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff( + new ContextualCardsDiffCallback(mContextualCards, contextualCards)); mContextualCards.clear(); mContextualCards.addAll(contextualCards); + diffResult.dispatchUpdatesTo(this); } - notifyDataSetChanged(); } } diff --git a/src/com/android/settings/homepage/ContextualCardsDiffCallback.java b/src/com/android/settings/homepage/ContextualCardsDiffCallback.java new file mode 100644 index 00000000000..84c6884d458 --- /dev/null +++ b/src/com/android/settings/homepage/ContextualCardsDiffCallback.java @@ -0,0 +1,58 @@ +/* + * 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.homepage; + +import androidx.recyclerview.widget.DiffUtil; + +import java.util.List; + +//TODO(b/117816826): add test cases for DiffUtil. +/** + * A DiffCallback to calculate the difference between old and new {@link ContextualCard} List. + */ +public class ContextualCardsDiffCallback extends DiffUtil.Callback { + + private final List mOldCards; + private final List mNewCards; + + public ContextualCardsDiffCallback(List oldCards, + List newCards) { + mOldCards = oldCards; + mNewCards = newCards; + } + + @Override + public int getOldListSize() { + return mOldCards.size(); + } + + @Override + public int getNewListSize() { + return mNewCards.size(); + } + + @Override + public boolean areItemsTheSame(int oldCardPosition, int newCardPosition) { + return mOldCards.get(oldCardPosition).getName().equals( + mNewCards.get(newCardPosition).getName()); + } + + @Override + public boolean areContentsTheSame(int oldCardPosition, int newCardPosition) { + return mOldCards.get(oldCardPosition).equals(mNewCards.get(newCardPosition)); + } +} \ No newline at end of file diff --git a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java index fbbab14ca3e..6a9c8dbe225 100644 --- a/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java +++ b/src/com/android/settings/homepage/conditional/ConditionContextualCardController.java @@ -37,6 +37,8 @@ import java.util.Map; public class ConditionContextualCardController implements ContextualCardController, ConditionListener, LifecycleObserver, OnStart, OnStop { + private static final String TAG = "ConditionCtxCardCtrl"; + private final Context mContext; private final ConditionManager mConditionManager; diff --git a/src/com/android/settings/homepage/conditional/ConditionManager.java b/src/com/android/settings/homepage/conditional/ConditionManager.java index d1c9a27771c..036695fb08d 100644 --- a/src/com/android/settings/homepage/conditional/ConditionManager.java +++ b/src/com/android/settings/homepage/conditional/ConditionManager.java @@ -107,12 +107,12 @@ public class ConditionManager { */ public void startMonitoringStateChange() { if (mIsListeningToStateChange) { - Log.d(TAG, "Already listening to condition state changes, skipping"); - return; - } - mIsListeningToStateChange = true; - for (ConditionalCardController controller : mCardControllers) { - controller.startMonitoringStateChange(); + Log.d(TAG, "Already listening to condition state changes, skipping monitor setup"); + } else { + mIsListeningToStateChange = true; + for (ConditionalCardController controller : mCardControllers) { + controller.startMonitoringStateChange(); + } } // Force a refresh on listener onConditionChanged(); diff --git a/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java index 5818e18546a..29e9aedf26c 100644 --- a/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java +++ b/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java @@ -91,14 +91,16 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, if (sliceLiveData == null) { sliceLiveData = SliceLiveData.fromUri(mContext, uri); mSliceLiveDataMap.put(uri.toString(), sliceLiveData); - sliceLiveData.observe(mLifecycleOwner, slice -> { - if (slice == null) { - Log.w(TAG, "Slice is null"); - } - cardHolder.sliceView.setSlice(slice); - }); } + sliceLiveData.removeObservers(mLifecycleOwner); + sliceLiveData.observe(mLifecycleOwner, slice -> { + if (slice == null) { + Log.w(TAG, "Slice is null"); + } + cardHolder.sliceView.setSlice(slice); + }); + // Set this listener so we can log the interaction users make on the slice cardHolder.sliceView.setOnSliceActionListener(this); } diff --git a/src/com/android/settings/network/telephony/CarrierPreferenceController.java b/src/com/android/settings/network/telephony/CarrierPreferenceController.java index 957eaaaa01a..406ef7b1cd4 100644 --- a/src/com/android/settings/network/telephony/CarrierPreferenceController.java +++ b/src/com/android/settings/network/telephony/CarrierPreferenceController.java @@ -19,6 +19,7 @@ package com.android.settings.network.telephony; import android.content.Context; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; @@ -37,6 +38,7 @@ public class CarrierPreferenceController extends BasePreferenceController { public CarrierPreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = new CarrierConfigManager(context); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } public void init(int subId) { diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java index 07c58c15078..b94f7e5e80f 100644 --- a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java +++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java @@ -43,6 +43,7 @@ public class DataUsagePreferenceController extends BasePreferenceController { public DataUsagePreferenceController(Context context, String key) { super(context, key); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override diff --git a/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java b/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java index d6773ed3fe6..cc8e78d06da 100644 --- a/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java +++ b/src/com/android/settings/network/telephony/Enhanced4gLtePreferenceController.java @@ -17,6 +17,7 @@ package com.android.settings.network.telephony; import android.content.Context; +import android.os.Looper; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.PhoneStateListener; @@ -35,6 +36,9 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; +import java.util.ArrayList; +import java.util.List; + /** * Preference controller for "Enhanced 4G LTE" */ @@ -48,13 +52,15 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle @VisibleForTesting ImsManager mImsManager; private PhoneCallStateListener mPhoneStateListener; + private final List m4gLteListeners; private int mSubId; public Enhanced4gLtePreferenceController(Context context, String key) { super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); - mPhoneStateListener = new PhoneCallStateListener(); - mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + m4gLteListeners = new ArrayList<>(); + mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper()); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override @@ -104,6 +110,9 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle @Override public boolean setChecked(boolean isChecked) { mImsManager.setEnhanced4gLteModeSetting(isChecked); + for (final On4gLteUpdateListener lsn : m4gLteListeners) { + lsn.on4gLteUpdated(); + } return true; } @@ -112,13 +121,20 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle return mImsManager.isEnhanced4gLteModeSettingEnabledByUser(); } - public void init(int subId) { + public Enhanced4gLtePreferenceController init(int subId) { mSubId = subId; mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId)); } + + return this; + } + + public Enhanced4gLtePreferenceController addListener(On4gLteUpdateListener lsn) { + m4gLteListeners.add(lsn); + return this; } private boolean is4gLtePrefEnabled() { @@ -131,6 +147,11 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle } private class PhoneCallStateListener extends PhoneStateListener { + + public PhoneCallStateListener(Looper looper) { + super(looper); + } + @Override public void onCallStateChanged(int state, String incomingNumber) { updateState(mPreference); @@ -145,4 +166,11 @@ public class Enhanced4gLtePreferenceController extends TogglePreferenceControlle mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); } } + + /** + * Update other preferences when 4gLte state is changed + */ + public interface On4gLteUpdateListener { + void on4gLteUpdated(); + } } diff --git a/src/com/android/settings/network/telephony/EuiccPreferenceController.java b/src/com/android/settings/network/telephony/EuiccPreferenceController.java new file mode 100644 index 00000000000..8d0390840dd --- /dev/null +++ b/src/com/android/settings/network/telephony/EuiccPreferenceController.java @@ -0,0 +1,74 @@ +/* + * 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.os.PersistableBundle; +import android.provider.Settings; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.telephony.euicc.EuiccManager; +import android.text.TextUtils; + +import androidx.preference.Preference; + +import com.android.settings.core.BasePreferenceController; + +/** + * Preference controller for "Euicc preference" + */ +public class EuiccPreferenceController extends BasePreferenceController { + + private TelephonyManager mTelephonyManager; + private int mSubId; + + public EuiccPreferenceController(Context context, String key) { + super(context, key); + mTelephonyManager = context.getSystemService(TelephonyManager.class); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + + @Override + public int getAvailabilityStatus() { + return MobileNetworkUtils.showEuiccSettings(mContext) + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public CharSequence getSummary() { + return mTelephonyManager.getSimOperatorName(); + } + + public void init(int subId) { + mSubId = subId; + mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (TextUtils.equals(preference.getKey(), getPreferenceKey())) { + Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS); + mContext.startActivity(intent); + return true; + } + + return false; + } +} diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java index 6958a11a341..065f18261aa 100644 --- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java +++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java @@ -61,6 +61,7 @@ public class MobileDataPreferenceController extends TogglePreferenceController super(context, key); mSubscriptionManager = context.getSystemService(SubscriptionManager.class); mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override diff --git a/src/com/android/settings/network/telephony/MobileNetworkFragment.java b/src/com/android/settings/network/telephony/MobileNetworkFragment.java index cb54e5b17d6..b31c1a10991 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkFragment.java +++ b/src/com/android/settings/network/telephony/MobileNetworkFragment.java @@ -26,22 +26,17 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.database.ContentObserver; -import android.net.Uri; -import android.os.AsyncTask; import android.os.Bundle; -import android.os.Message; import android.os.PersistableBundle; import android.os.UserManager; import android.provider.SearchIndexableResource; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; -import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; -import android.telephony.euicc.EuiccManager; import android.text.TextUtils; import android.util.Log; import android.view.MenuItem; @@ -51,9 +46,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; -import com.android.ims.ImsConfig; import com.android.ims.ImsManager; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; @@ -93,8 +86,6 @@ public class MobileNetworkFragment extends DashboardFragment implements private static final String BUTTON_CDMA_SUBSCRIPTION_KEY = "cdma_subscription_key"; private static final String BUTTON_CARRIER_SETTINGS_EUICC_KEY = "carrier_settings_euicc_key"; - private static final String BUTTON_WIFI_CALLING_KEY = "wifi_calling_key"; - private static final String BUTTON_VIDEO_CALLING_KEY = "video_calling_key"; private static final String BUTTON_MOBILE_DATA_ENABLE_KEY = "mobile_data_enable"; private static final String BUTTON_DATA_USAGE_KEY = "data_usage_summary"; private static final String BUTTON_ADVANCED_OPTIONS_KEY = "advanced_options"; @@ -120,14 +111,6 @@ public class MobileNetworkFragment extends DashboardFragment implements private CarrierConfigManager mCarrierConfigManager; private int mSubId; - //UI objects - private SwitchPreference mButton4glte; - private Preference mEuiccSettingsPref; - private PreferenceCategory mCallingCategory; - private Preference mWiFiCallingPref; - private SwitchPreference mVideoCallingPref; - private NetworkSelectListPreference mButtonNetworkSelect; - private CdmaSystemSelectPreferenceController mCdmaSystemSelectPreferenceController; private CdmaSubscriptionPreferenceController mCdmaSubscriptionPreferenceController; @@ -148,44 +131,6 @@ public class MobileNetworkFragment extends DashboardFragment implements private boolean mOnlyAutoSelectInHomeNW; private boolean mUnavailable; - private class PhoneCallStateListener extends PhoneStateListener { - /* - * Enable/disable the 'Enhanced 4G LTE Mode' when in/out of a call - * and depending on TTY mode and TTY support over VoLTE. - * @see android.telephony.PhoneStateListener#onCallStateChanged(int, - * java.lang.String) - */ - @Override - public void onCallStateChanged(int state, String incomingNumber) { - if (DBG) log("PhoneStateListener.onCallStateChanged: state=" + state); - - updateWiFiCallState(); - updateVideoCallState(); - updatePreferredNetworkType(); - } - - /** - * Listen to different subId if it's changed. - */ - protected void updateSubscriptionId(Integer subId) { - if (subId.equals(PhoneCallStateListener.this.mSubId)) { - return; - } - - PhoneCallStateListener.this.mSubId = subId; - - mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); - - // Now, listen to new subId if it's valid. - if (SubscriptionManager.isValidSubscriptionId(subId)) { - mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE); - } - } - } - - private final PhoneCallStateListener - mPhoneStateListener = new PhoneCallStateListener(); - @Override public int getMetricsCategory() { //TODO(b/114749736): add metrics id for it @@ -222,15 +167,9 @@ public class MobileNetworkFragment extends DashboardFragment implements REQUEST_CODE_EXIT_ECM); } return true; - } else if (preference == mEuiccSettingsPref) { - Intent intent = new Intent(EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS); - startActivity(intent); - return true; - } else if (preference == mWiFiCallingPref || preference == mVideoCallingPref) { - return false; } - return true; + return false; } private final SubscriptionManager.OnSubscriptionsChangedListener @@ -260,8 +199,6 @@ public class MobileNetworkFragment extends DashboardFragment implements SubscriptionManager.getPhoneId(mSubId)); mTelephonyManager = new TelephonyManager(getContext(), mSubId); } - - mPhoneStateListener.updateSubscriptionId(mSubId); } @Override @@ -277,13 +214,19 @@ public class MobileNetworkFragment extends DashboardFragment implements use(DataUsagePreferenceController.class).init(mSubId); use(PreferredNetworkModePreferenceController.class).init(mSubId); use(EnabledNetworkModePreferenceController.class).init(mSubId); - use(Enhanced4gLtePreferenceController.class).init(mSubId); use(DataServiceSetupPreferenceController.class).init(mSubId); + use(EuiccPreferenceController.class).init(mSubId); + use(WifiCallingPreferenceController.class).init(mSubId); mCdmaSystemSelectPreferenceController = use(CdmaSystemSelectPreferenceController.class); mCdmaSystemSelectPreferenceController.init(getPreferenceManager(), mSubId); mCdmaSubscriptionPreferenceController = use(CdmaSubscriptionPreferenceController.class); mCdmaSubscriptionPreferenceController.init(getPreferenceManager(), mSubId); + + final VideoCallingPreferenceController videoCallingPreferenceController = + use(VideoCallingPreferenceController.class).init(mSubId); + use(Enhanced4gLtePreferenceController.class).init(mSubId) + .addListener(videoCallingPreferenceController); } @Override @@ -303,12 +246,6 @@ public class MobileNetworkFragment extends DashboardFragment implements Context.TELEPHONY_SERVICE); mCarrierConfigManager = new CarrierConfigManager(getContext()); - mButton4glte = (SwitchPreference)findPreference(BUTTON_4G_LTE_KEY); - - mCallingCategory = (PreferenceCategory) findPreference(CATEGORY_CALLING_KEY); - mWiFiCallingPref = findPreference(BUTTON_WIFI_CALLING_KEY); - mVideoCallingPref = (SwitchPreference) findPreference(BUTTON_VIDEO_CALLING_KEY); - try { Context con = context.createPackageContext("com.android.systemui", 0); int id = con.getResources().getIdentifier("config_show4GForLTE", @@ -319,12 +256,6 @@ public class MobileNetworkFragment extends DashboardFragment implements mShow4GForLTE = false; } - //get UI object references - PreferenceScreen prefSet = getPreferenceScreen(); - - mEuiccSettingsPref = prefSet.findPreference(BUTTON_CARRIER_SETTINGS_EUICC_KEY); - mEuiccSettingsPref.setOnPreferenceChangeListener(this); - // Initialize mActiveSubInfo int max = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); mActiveSubInfos = mSubscriptionManager.getActiveSubscriptionInfoList(); @@ -388,11 +319,6 @@ public class MobileNetworkFragment extends DashboardFragment implements // preferences. getPreferenceScreen().setEnabled(true); - mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); - - // Video calling and WiFi calling state might have changed. - updateCallingCategory(); - mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener); final Context context = getContext(); @@ -450,12 +376,6 @@ public class MobileNetworkFragment extends DashboardFragment implements if (hasActiveSubscriptions) { updateBodyAdvancedFields(activity, prefSet, mSubId, hasActiveSubscriptions); - } else { - // Shows the "Carrier" preference that allows user to add a e-sim profile. - if (MobileNetworkUtils.showEuiccSettings(getContext())) { - mEuiccSettingsPref.setSummary(null /* summary */); - prefSet.addPreference(mEuiccSettingsPref); - } } } @@ -468,16 +388,6 @@ public class MobileNetworkFragment extends DashboardFragment implements log("updateBody: isLteOnCdma=" + isLteOnCdma + " phoneSubId=" + phoneSubId); } - if (MobileNetworkUtils.showEuiccSettings(getContext())) { - prefSet.addPreference(mEuiccSettingsPref); - String spn = mTelephonyManager.getSimOperatorName(); - if (TextUtils.isEmpty(spn)) { - mEuiccSettingsPref.setSummary(null); - } else { - mEuiccSettingsPref.setSummary(spn); - } - } - int settingsNetworkMode = android.provider.Settings.Global.getInt( getContext().getContentResolver(), android.provider.Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId, @@ -518,9 +428,6 @@ public class MobileNetworkFragment extends DashboardFragment implements android.provider.Settings.Global.getString(activity.getContentResolver(), android.provider.Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL)); - updatePreferredNetworkType(); - updateCallingCategory(); - // Enable link to CMAS app settings depending on the value in config.xml. final boolean isCellBroadcastAppLinkEnabled = activity.getResources().getBoolean( com.android.internal.R.bool.config_cellBroadcastAppLinks); @@ -581,8 +488,6 @@ public class MobileNetworkFragment extends DashboardFragment implements super.onPause(); if (DBG) log("onPause:+"); - mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); - mSubscriptionManager .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener); @@ -602,18 +507,6 @@ public class MobileNetworkFragment extends DashboardFragment implements */ public boolean onPreferenceChange(Preference preference, Object objValue) { sendMetricsEventPreferenceChanged(getPreferenceScreen(), preference, objValue); - if (preference == mVideoCallingPref) { - // If mButton4glte is not checked, mVideoCallingPref should be disabled. - // So it only makes sense to call phoneMgr.enableVideoCalling if it's checked. - if (mButton4glte.isChecked()) { - mImsMgr.setVtSetting((boolean) objValue); - return true; - } else { - loge("mVideoCallingPref should be disabled if mButton4glte is not checked."); - mVideoCallingPref.setEnabled(false); - return false; - } - } updateBody(); // always let the preference setting proceed. @@ -655,111 +548,6 @@ public class MobileNetworkFragment extends DashboardFragment implements } } - private void updateWiFiCallState() { - if (mWiFiCallingPref == null || mCallingCategory == null) { - return; - } - - // Removes the preference if the wifi calling is disabled. - if (!MobileNetworkUtils.isWifiCallingEnabled(getContext(), - SubscriptionManager.getPhoneId(mSubId))) { - mCallingCategory.removePreference(mWiFiCallingPref); - return; - } - - final PhoneAccountHandle simCallManager = - TelecomManager.from(getContext()).getSimCallManager(); - - if (simCallManager != null) { - Intent intent = buildPhoneAccountConfigureIntent(getContext(), simCallManager); - PackageManager pm = getContext().getPackageManager(); - List resolutions = pm.queryIntentActivities(intent, 0); - mWiFiCallingPref.setTitle(resolutions.get(0).loadLabel(pm)); - mWiFiCallingPref.setSummary(null); - mWiFiCallingPref.setIntent(intent); - } else { - int resId = com.android.internal.R.string.wifi_calling_off_summary; - if (mImsMgr.isWfcEnabledByUser()) { - boolean isRoaming = mTelephonyManager.isNetworkRoaming(); - int wfcMode = mImsMgr.getWfcMode(isRoaming); - - switch (wfcMode) { - case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY: - resId = com.android.internal.R.string.wfc_mode_wifi_only_summary; - break; - case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED: - resId = com.android.internal.R.string - .wfc_mode_cellular_preferred_summary; - break; - case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED: - resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary; - break; - default: - if (DBG) log("Unexpected WFC mode value: " + wfcMode); - } - } - mWiFiCallingPref.setSummary(resId); - } - - mCallingCategory.addPreference(mWiFiCallingPref); - mWiFiCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId) - == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions()); - } - - private void updateVideoCallState() { - if (mVideoCallingPref == null || mCallingCategory == null) { - return; - } - - PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); - - if (mImsMgr != null - && mImsMgr.isVtEnabledByPlatform() - && mImsMgr.isVtProvisionedOnDevice() - && MobileNetworkUtils.isImsServiceStateReady(mImsMgr) - && (carrierConfig.getBoolean( - CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS) - || mTelephonyManager.isDataEnabled())) { - mCallingCategory.addPreference(mVideoCallingPref); - if (!mButton4glte.isChecked()) { - mVideoCallingPref.setEnabled(false); - mVideoCallingPref.setChecked(false); - } else { - mVideoCallingPref.setEnabled(mTelephonyManager.getCallState(mSubId) - == TelephonyManager.CALL_STATE_IDLE && hasActiveSubscriptions()); - mVideoCallingPref.setChecked(mImsMgr.isVtEnabledByUser()); - mVideoCallingPref.setOnPreferenceChangeListener(this); - } - } else { - mCallingCategory.removePreference(mVideoCallingPref); - } - } - - private void updatePreferredNetworkType() { - boolean enabled = mTelephonyManager.getCallState( - mSubId) == TelephonyManager.CALL_STATE_IDLE - && hasActiveSubscriptions(); - Log.i(LOG_TAG, "updatePreferredNetworkType: " + enabled); - } - - private void updateCallingCategory() { - if (mCallingCategory == null) { - return; - } - - updateWiFiCallState(); - updateVideoCallState(); - - // If all items in calling category is removed, we remove it from - // the screen. Otherwise we'll see title of the category but nothing - // is in there. - if (mCallingCategory.getPreferenceCount() == 0) { - getPreferenceScreen().removePreference(mCallingCategory); - } else { - getPreferenceScreen().addPreference(mCallingCategory); - } - } - private static void log(String msg) { Log.d(LOG_TAG, msg); } @@ -880,9 +668,7 @@ public class MobileNetworkFragment extends DashboardFragment implements // For ListPreferences, we log it here without a value, only indicating it's clicked to // open the list dialog. When a value is chosen, another MetricsEvent is logged with // new value in onPreferenceChange. - if (preference == mEuiccSettingsPref - || preference == mWiFiCallingPref - || preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY) + if (preference == preferenceScreen.findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY) || preference == preferenceScreen.findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY) || preference == preferenceScreen.findPreference(BUTTON_GSM_APN_EXPAND_KEY) || preference == preferenceScreen.findPreference(BUTTON_CDMA_APN_EXPAND_KEY) @@ -899,9 +685,7 @@ public class MobileNetworkFragment extends DashboardFragment implements } // MetricsEvent logging with new value, for SwitchPreferences and ListPreferences. - if (preference == mVideoCallingPref) { - MetricsLogger.action(getContext(), category, (Boolean) newValue); - } else if (preference == preferenceScreen + if (preference == preferenceScreen .findPreference(BUTTON_CDMA_SYSTEM_SELECT_KEY) || preference == preferenceScreen .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY)) { @@ -915,12 +699,6 @@ public class MobileNetworkFragment extends DashboardFragment implements if (preference == null) { return MetricsProto.MetricsEvent.VIEW_UNKNOWN; - } else if (preference == mEuiccSettingsPref) { - return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_EUICC_SETTING; - } else if (preference == mWiFiCallingPref) { - return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_WIFI_CALLING; - } else if (preference == mVideoCallingPref) { - return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_VIDEO_CALLING_TOGGLE; } else if (preference == preferenceScreen .findPreference(NetworkOperators.BUTTON_AUTO_SELECT_KEY)) { return MetricsProto.MetricsEvent.ACTION_MOBILE_NETWORK_AUTO_SELECT_NETWORK_TOGGLE; @@ -1024,31 +802,4 @@ public class MobileNetworkFragment extends DashboardFragment implements return result; } }; - - private static final class SetPreferredNetworkAsyncTask extends AsyncTask { - - private final TelephonyManager mTelephonyManager; - private final int mSubId; - private final int mNetworkType; - private final Message mCallback; - - SetPreferredNetworkAsyncTask( - TelephonyManager tm, int subId, int networkType, Message callback) { - mTelephonyManager = tm; - mSubId = subId; - mNetworkType = networkType; - mCallback = callback; - } - - @Override - protected Boolean doInBackground(Void... voids) { - return mTelephonyManager.setPreferredNetworkType(mSubId, mNetworkType); - } - - @Override - protected void onPostExecute(Boolean isSuccessed) { - mCallback.obj = isSuccessed; - mCallback.sendToTarget(); - } - } } diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.java b/src/com/android/settings/network/telephony/RoamingPreferenceController.java index 3c1741bb0da..b2eba08f9f9 100644 --- a/src/com/android/settings/network/telephony/RoamingPreferenceController.java +++ b/src/com/android/settings/network/telephony/RoamingPreferenceController.java @@ -61,6 +61,7 @@ public class RoamingPreferenceController extends TogglePreferenceController impl super(context, key); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } @Override diff --git a/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java new file mode 100644 index 00000000000..1007ef8e03a --- /dev/null +++ b/src/com/android/settings/network/telephony/VideoCallingPreferenceController.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network.telephony; + +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.os.PersistableBundle; +import android.provider.Settings; +import android.telephony.CarrierConfigManager; +import android.telephony.PhoneStateListener; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; + +import com.android.ims.ImsManager; +import com.android.settings.core.TogglePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +/** + * Preference controller for "Video Calling" + */ +public class VideoCallingPreferenceController extends TogglePreferenceController implements + LifecycleObserver, OnStart, OnStop, + Enhanced4gLtePreferenceController.On4gLteUpdateListener { + + private Preference mPreference; + private TelephonyManager mTelephonyManager; + private CarrierConfigManager mCarrierConfigManager; + private PersistableBundle mCarrierConfig; + @VisibleForTesting + ImsManager mImsManager; + private PhoneCallStateListener mPhoneStateListener; + private DataContentObserver mDataContentObserver; + private int mSubId; + + public VideoCallingPreferenceController(Context context, String key) { + super(context, key); + mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); + mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); + mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper()); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + + @Override + public int getAvailabilityStatus() { + return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + && MobileNetworkUtils.isWifiCallingEnabled(mContext, + SubscriptionManager.getPhoneId(mSubId)) + && isVideoCallEnabled() + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + + @Override + public void onStart() { + mPhoneStateListener.register(mSubId); + mDataContentObserver.register(mContext, mSubId); + } + + @Override + public void onStop() { + mPhoneStateListener.unregister(); + mDataContentObserver.unRegister(mContext); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + final SwitchPreference switchPreference = (SwitchPreference) preference; + final boolean videoCallEnabled = isVideoCallEnabled(); + switchPreference.setVisible(videoCallEnabled); + if (videoCallEnabled) { + final boolean is4gLteEnabled = mImsManager.isEnhanced4gLteModeSettingEnabledByUser() + && mImsManager.isNonTtyOrTtyOnVolteEnabled(); + preference.setEnabled(is4gLteEnabled && + mTelephonyManager.getCallState(mSubId) == TelephonyManager.CALL_STATE_IDLE); + switchPreference.setChecked(is4gLteEnabled && mImsManager.isVtEnabledByUser()); + } + } + + @Override + public boolean setChecked(boolean isChecked) { + mImsManager.setVtSetting(isChecked); + return true; + } + + @Override + public boolean isChecked() { + return mImsManager.isVtEnabledByUser(); + } + + public VideoCallingPreferenceController init(int subId) { + mSubId = subId; + mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); + mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId); + if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId)); + } + + return this; + } + + @VisibleForTesting + boolean isVideoCallEnabled() { + return mCarrierConfig != null && mImsManager != null + && mImsManager.isVtEnabledByPlatform() + && mImsManager.isVtProvisionedOnDevice() + && MobileNetworkUtils.isImsServiceStateReady(mImsManager) + && (mCarrierConfig.getBoolean( + CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS) + || mTelephonyManager.isDataEnabled()); + } + + @Override + public void on4gLteUpdated() { + updateState(mPreference); + } + + private class PhoneCallStateListener extends PhoneStateListener { + + public PhoneCallStateListener(Looper looper) { + super(looper); + } + + @Override + public void onCallStateChanged(int state, String incomingNumber) { + updateState(mPreference); + } + + public void register(int subId) { + mSubId = subId; + mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE); + } + + public void unregister() { + mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); + } + } + + /** + * Listener that listens mobile data state change. + */ + public class DataContentObserver extends ContentObserver { + + public DataContentObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + updateState(mPreference); + } + + public void register(Context context, int subId) { + Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA); + if (TelephonyManager.getDefault().getSimCount() != 1) { + uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId); + } + context.getContentResolver().registerContentObserver(uri, + false /* notifyForDescendants */, this /* observer */); + } + + public void unRegister(Context context) { + context.getContentResolver().unregisterContentObserver(this); + } + } +} diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java new file mode 100644 index 00000000000..09bf2d72ca2 --- /dev/null +++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network.telephony; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Looper; +import android.telecom.PhoneAccountHandle; +import android.telecom.TelecomManager; +import android.telephony.PhoneStateListener; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.ims.ImsConfig; +import com.android.ims.ImsManager; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +import java.util.List; + +/** + * Preference controller for "Wifi Calling" + */ +public class WifiCallingPreferenceController extends BasePreferenceController implements + LifecycleObserver, OnStart, OnStop { + + private TelephonyManager mTelephonyManager; + @VisibleForTesting + ImsManager mImsManager; + @VisibleForTesting + PhoneAccountHandle mSimCallManager; + private PhoneCallStateListener mPhoneStateListener; + private Preference mPreference; + private int mSubId; + + public WifiCallingPreferenceController(Context context, String key) { + super(context, key); + mTelephonyManager = context.getSystemService(TelephonyManager.class); + mSimCallManager = context.getSystemService(TelecomManager.class).getSimCallManager(); + mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper()); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + + @Override + public int getAvailabilityStatus() { + return mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + && MobileNetworkUtils.isWifiCallingEnabled(mContext, + SubscriptionManager.getPhoneId(mSubId)) + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void onStart() { + mPhoneStateListener.register(mSubId); + } + + @Override + public void onStop() { + mPhoneStateListener.unregister(); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (mSimCallManager != null) { + Intent intent = MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, + mSimCallManager); + final PackageManager pm = mContext.getPackageManager(); + List resolutions = pm.queryIntentActivities(intent, 0); + preference.setTitle(resolutions.get(0).loadLabel(pm)); + preference.setSummary(null); + preference.setIntent(intent); + } else { + int resId = com.android.internal.R.string.wifi_calling_off_summary; + if (mImsManager.isWfcEnabledByUser()) { + final boolean isRoaming = mTelephonyManager.isNetworkRoaming(); + int wfcMode = mImsManager.getWfcMode(isRoaming); + + switch (wfcMode) { + case ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY: + resId = com.android.internal.R.string.wfc_mode_wifi_only_summary; + break; + case ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED: + resId = com.android.internal.R.string + .wfc_mode_cellular_preferred_summary; + break; + case ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED: + resId = com.android.internal.R.string.wfc_mode_wifi_preferred_summary; + break; + default: + break; + } + } + preference.setSummary(resId); + } + preference.setEnabled( + mTelephonyManager.getCallState(mSubId) == TelephonyManager.CALL_STATE_IDLE); + } + + public void init(int subId) { + mSubId = subId; + mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); + mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId)); + } + + private class PhoneCallStateListener extends PhoneStateListener { + + public PhoneCallStateListener(Looper looper) { + super(looper); + } + + @Override + public void onCallStateChanged(int state, String incomingNumber) { + updateState(mPreference); + } + + public void register(int subId) { + mSubId = subId; + mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE); + } + + public void unregister() { + mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); + } + } +} diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionManagerTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionManagerTest.java index 014a4a151fd..3fbac17a897 100644 --- a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionManagerTest.java +++ b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionManagerTest.java @@ -19,6 +19,8 @@ package com.android.settings.homepage.conditional; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -53,7 +55,7 @@ public class ConditionManagerTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; - mManager = new ConditionManager(mContext, mConditionListener); + mManager = spy(new ConditionManager(mContext, mConditionListener)); assertThat(mManager.mCandidates.size()).isEqualTo(mManager.mCardControllers.size()); @@ -94,11 +96,13 @@ public class ConditionManagerTest { @Test public void startMonitoringStateChange_multipleTimes_shouldRegisterOnce() { - mManager.startMonitoringStateChange(); - mManager.startMonitoringStateChange(); - mManager.startMonitoringStateChange(); + final int loopCount = 10; + for (int i = 0; i < loopCount; i++) { + mManager.startMonitoringStateChange(); + } verify(mController).startMonitoringStateChange(); + verify(mManager, times(loopCount)).onConditionChanged(); } @Test diff --git a/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java index c5ca8d79487..b8f8415a0dc 100644 --- a/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java +++ b/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java @@ -18,7 +18,7 @@ package com.android.settings.homepage.slices; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import android.content.Context; import android.net.Uri; @@ -26,8 +26,10 @@ import android.view.LayoutInflater; import android.view.View; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LiveData; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import androidx.slice.Slice; import com.android.settings.homepage.ContextualCard; import com.android.settings.homepage.PersonalSettingsFragment; @@ -36,12 +38,16 @@ 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 SliceContextualCardRendererTest { + @Mock + private LiveData mSliceLiveData; + private Context mContext; private SliceContextualCardRenderer mRenderer; private LifecycleOwner mLifecycleOwner; @@ -96,6 +102,16 @@ public class SliceContextualCardRendererTest { assertThat(mRenderer.mSliceLiveDataMap.get(sliceUri).hasObservers()).isTrue(); } + @Test + public void bindview_sliceLiveDataShouldRemoveObservers() { + final String sliceUri = "content://com.android.settings.slices/action/flashlight"; + mRenderer.mSliceLiveDataMap.put(sliceUri, mSliceLiveData); + + mRenderer.bindView(getSliceViewHolder(), buildContextualCard(sliceUri)); + + verify(mSliceLiveData).removeObservers(mLifecycleOwner); + } + private RecyclerView.ViewHolder getSliceViewHolder() { final int viewType = mRenderer.getViewType(); final RecyclerView recyclerView = new RecyclerView(mContext); diff --git a/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java new file mode 100644 index 00000000000..89e299c2e3e --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/EuiccPreferenceControllerTest.java @@ -0,0 +1,78 @@ +/* + * 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 static org.mockito.Mockito.verify; + +import android.content.Context; +import android.content.Intent; +import android.telephony.TelephonyManager; +import android.telephony.euicc.EuiccManager; + +import androidx.preference.Preference; + +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class EuiccPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + + private EuiccPreferenceController 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 EuiccPreferenceController(mContext, "euicc"); + mController.init(SUB_ID); + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void handlePreferenceTreeClick_startActivity() { + ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); + + mController.handlePreferenceTreeClick(mPreference); + + verify(mContext).startActivity(captor.capture()); + assertThat(captor.getValue().getAction()).isEqualTo( + EuiccManager.ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS); + } + +} diff --git a/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java new file mode 100644 index 00000000000..e50e2646e5a --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network.telephony; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.os.PersistableBundle; +import android.telephony.CarrierConfigManager; +import android.telephony.TelephonyManager; +import android.telephony.ims.feature.ImsFeature; + +import androidx.preference.SwitchPreference; + +import com.android.ims.ImsManager; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class VideoCallingPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private ImsManager mImsManager; + @Mock + private CarrierConfigManager mCarrierConfigManager; + + private VideoCallingPreferenceController mController; + private PersistableBundle mCarrierConfig; + private SwitchPreference mPreference; + private Context mContext; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); + doReturn(mTelephonyManager).when(mContext).getSystemService(TelephonyManager.class); + doReturn(mCarrierConfigManager).when(mContext).getSystemService(CarrierConfigManager.class); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + + mCarrierConfig = new PersistableBundle(); + mCarrierConfig.putBoolean( + CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true); + doReturn(mCarrierConfig).when(mCarrierConfigManager).getConfigForSubId(SUB_ID); + + mPreference = new SwitchPreference(mContext); + mController = new VideoCallingPreferenceController(mContext, "wifi_calling"); + mController.init(SUB_ID); + mController.mImsManager = mImsManager; + mPreference.setKey(mController.getPreferenceKey()); + + doReturn(true).when(mImsManager).isVtEnabledByPlatform(); + doReturn(true).when(mImsManager).isVtProvisionedOnDevice(); + doReturn(ImsFeature.STATE_READY).when(mImsManager).getImsServiceState(); + doReturn(true).when(mTelephonyManager).isDataEnabled(); + } + + @Test + public void isVideoCallEnabled_allFlagsOn_returnTrue() { + assertThat(mController.isVideoCallEnabled()).isTrue(); + } + + @Test + public void isVideoCallEnabled_disabledByPlatform_returnFalse() { + doReturn(false).when(mImsManager).isVtEnabledByPlatform(); + + assertThat(mController.isVideoCallEnabled()).isFalse(); + } + + @Test + public void isVideoCallEnabled_dataDisabled_returnFalse() { + mCarrierConfig.putBoolean( + CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, false); + doReturn(false).when(mTelephonyManager).isDataEnabled(); + + assertThat(mController.isVideoCallEnabled()).isFalse(); + } + + @Test + public void updateState_4gLteOff_disabled() { + doReturn(false).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser(); + + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + assertThat(mPreference.isChecked()).isFalse(); + } + + @Test + public void updateState_4gLteOnWithoutCall_checked() { + doReturn(true).when(mImsManager).isVtEnabledByUser(); + doReturn(true).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser(); + doReturn(true).when(mImsManager).isNonTtyOrTtyOnVolteEnabled(); + doReturn(TelephonyManager.CALL_STATE_IDLE).when(mTelephonyManager).getCallState(SUB_ID); + + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isTrue(); + assertThat(mPreference.isChecked()).isTrue(); + } + +} diff --git a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java new file mode 100644 index 00000000000..35297bd8d58 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network.telephony; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.content.Context; +import android.telecom.PhoneAccountHandle; +import android.telephony.TelephonyManager; + +import androidx.preference.Preference; + +import com.android.ims.ImsConfig; +import com.android.ims.ImsManager; +import com.android.settings.testutils.SettingsRobolectricTestRunner; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; + +@RunWith(SettingsRobolectricTestRunner.class) +public class WifiCallingPreferenceControllerTest { + private static final int SUB_ID = 2; + + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private ImsManager mImsManager; + + private WifiCallingPreferenceController mController; + private Preference mPreference; + private Context mContext; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext = spy(RuntimeEnvironment.application); + doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); + doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID); + + mPreference = new Preference(mContext); + mController = new WifiCallingPreferenceController(mContext, "wifi_calling"); + mController.init(SUB_ID); + mController.mImsManager = mImsManager; + mPreference.setKey(mController.getPreferenceKey()); + } + + @Test + public void updateState_noSimCallManager_setCorrectSummary() { + mController.mSimCallManager = null; + doReturn(true).when(mImsManager).isWfcEnabledByUser(); + doReturn(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY).when(mImsManager).getWfcMode( + anyBoolean()); + + mController.updateState(mPreference); + + assertThat(mPreference.getSummary()).isEqualTo( + mContext.getString(com.android.internal.R.string.wfc_mode_wifi_only_summary)); + } + + @Test + public void updateState_notCallIdle_disable() { + doReturn(TelephonyManager.CALL_STATE_RINGING).when(mTelephonyManager).getCallState(SUB_ID); + + mController.updateState(mPreference); + + assertThat(mPreference.isEnabled()).isFalse(); + } + +}