diff --git a/res/xml/network_and_internet.xml b/res/xml/network_and_internet.xml index e990f9d2622..bce5dd93652 100644 --- a/res/xml/network_and_internet.xml +++ b/res/xml/network_and_internet.xml @@ -54,4 +54,30 @@ settings:userRestriction="no_config_vpn" settings:useAdminDisabledSummary="true"/> + + + + + + + + \ No newline at end of file diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java index 5453b5e64a9..e18f0221fd5 100644 --- a/src/com/android/settings/WifiCallingSettings.java +++ b/src/com/android/settings/WifiCallingSettings.java @@ -443,7 +443,7 @@ public class WifiCallingSettings extends SettingsPreferenceFragment return true; } - static int getWfcModeSummary(Context context, int wfcMode) { + public static int getWfcModeSummary(Context context, int wfcMode) { int resId = com.android.internal.R.string.wifi_calling_off_summary; if (ImsManager.isWfcEnabledByUser(context)) { switch (wfcMode) { diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java index 99e9ac59f1a..5f7c759fb2d 100644 --- a/src/com/android/settings/WirelessSettings.java +++ b/src/com/android/settings/WirelessSettings.java @@ -20,15 +20,10 @@ package com.android.settings; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; -import android.app.admin.DevicePolicyManager; -import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.res.Resources; import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.net.Uri; import android.nfc.NfcAdapter; import android.nfc.NfcManager; import android.os.Bundle; @@ -40,16 +35,17 @@ import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.telephony.TelephonyManager; -import android.text.TextUtils; import android.util.Log; -import com.android.ims.ImsManager; import com.android.internal.logging.MetricsProto.MetricsEvent; -import com.android.internal.telephony.TelephonyIntents; import com.android.settings.network.AirplaneModePreferenceController; import com.android.settings.network.MobileNetworkPreferenceController; +import com.android.settings.network.MobilePlanPreferenceController; +import com.android.settings.network.NetworkResetPreferenceController; +import com.android.settings.network.ProxyPreferenceController; import com.android.settings.network.TetherPreferenceController; import com.android.settings.network.VpnPreferenceController; +import com.android.settings.network.WifiCallingPreferenceController; import com.android.settings.nfc.NfcEnabler; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; @@ -61,33 +57,29 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -public class WirelessSettings extends SettingsPreferenceFragment implements Indexable { +import static com.android.settings.network.MobilePlanPreferenceController + .MANAGE_MOBILE_PLAN_DIALOG_ID; + +public class WirelessSettings extends SettingsPreferenceFragment implements Indexable, + MobilePlanPreferenceController.MobilePlanPreferenceHost { private static final String TAG = "WirelessSettings"; private static final String KEY_TOGGLE_NFC = "toggle_nfc"; private static final String KEY_WIMAX_SETTINGS = "wimax_settings"; private static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings"; - private static final String KEY_PROXY_SETTINGS = "proxy_settings"; - - private static final String KEY_MANAGE_MOBILE_PLAN = "manage_mobile_plan"; - private static final String KEY_WFC_SETTINGS = "wifi_calling_settings"; - private static final String KEY_NETWORK_RESET = "network_reset"; private NfcEnabler mNfcEnabler; private NfcAdapter mNfcAdapter; - - private ConnectivityManager mCm; - private TelephonyManager mTm; private UserManager mUm; - private static final int MANAGE_MOBILE_PLAN_DIALOG_ID = 1; - private static final String SAVED_MANAGE_MOBILE_PLAN_MSG = "mManageMobilePlanMessage"; - - private PreferenceScreen mButtonWfc; private AirplaneModePreferenceController mAirplaneModePreferenceController; private TetherPreferenceController mTetherPreferenceController; private MobileNetworkPreferenceController mMobileNetworkPreferenceController; private VpnPreferenceController mVpnPreferenceController; + private NetworkResetPreferenceController mNetworkResetPreferenceController; + private WifiCallingPreferenceController mWifiCallingPreferenceController; + private ProxyPreferenceController mProxyPreferenceController; + private MobilePlanPreferenceController mMobilePlanPreferenceController; /** * Invoked on each preference click in this hierarchy, overrides @@ -100,96 +92,31 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde if (mAirplaneModePreferenceController.handlePreferenceTreeClick(preference)) { return true; } - if (preference == findPreference(KEY_MANAGE_MOBILE_PLAN)) { - onManageMobilePlanClick(); + if (mMobilePlanPreferenceController.handlePreferenceTreeClick(preference)) { + return true; } // Let the intents be launched by the Preference manager return super.onPreferenceTreeClick(preference); } - private String mManageMobilePlanMessage; - public void onManageMobilePlanClick() { - log("onManageMobilePlanClick:"); - mManageMobilePlanMessage = null; - Resources resources = getActivity().getResources(); - - NetworkInfo ni = mCm.getActiveNetworkInfo(); - if (mTm.hasIccCard() && (ni != null)) { - // Check for carrier apps that can handle provisioning first - Intent provisioningIntent = new Intent(TelephonyIntents.ACTION_CARRIER_SETUP); - List carrierPackages = - mTm.getCarrierPackageNamesForIntent(provisioningIntent); - if (carrierPackages != null && !carrierPackages.isEmpty()) { - if (carrierPackages.size() != 1) { - Log.w(TAG, "Multiple matching carrier apps found, launching the first."); - } - provisioningIntent.setPackage(carrierPackages.get(0)); - startActivity(provisioningIntent); - return; - } - - // Get provisioning URL - String url = mCm.getMobileProvisioningUrl(); - if (!TextUtils.isEmpty(url)) { - Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, - Intent.CATEGORY_APP_BROWSER); - intent.setData(Uri.parse(url)); - intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | - Intent.FLAG_ACTIVITY_NEW_TASK); - try { - startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.w(TAG, "onManageMobilePlanClick: startActivity failed" + e); - } - } else { - // No provisioning URL - String operatorName = mTm.getSimOperatorName(); - if (TextUtils.isEmpty(operatorName)) { - // Use NetworkOperatorName as second choice in case there is no - // SPN (Service Provider Name on the SIM). Such as with T-mobile. - operatorName = mTm.getNetworkOperatorName(); - if (TextUtils.isEmpty(operatorName)) { - mManageMobilePlanMessage = resources.getString( - R.string.mobile_unknown_sim_operator); - } else { - mManageMobilePlanMessage = resources.getString( - R.string.mobile_no_provisioning_url, operatorName); - } - } else { - mManageMobilePlanMessage = resources.getString( - R.string.mobile_no_provisioning_url, operatorName); - } - } - } else if (mTm.hasIccCard() == false) { - // No sim card - mManageMobilePlanMessage = resources.getString(R.string.mobile_insert_sim_card); - } else { - // NetworkInfo is null, there is no connection - mManageMobilePlanMessage = resources.getString(R.string.mobile_connect_to_internet); - } - if (!TextUtils.isEmpty(mManageMobilePlanMessage)) { - log("onManageMobilePlanClick: message=" + mManageMobilePlanMessage); - showDialog(MANAGE_MOBILE_PLAN_DIALOG_ID); - } - } - @Override public Dialog onCreateDialog(int dialogId) { log("onCreateDialog: dialogId=" + dialogId); switch (dialogId) { case MANAGE_MOBILE_PLAN_DIALOG_ID: return new AlertDialog.Builder(getActivity()) - .setMessage(mManageMobilePlanMessage) - .setCancelable(false) - .setPositiveButton(com.android.internal.R.string.ok, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - log("MANAGE_MOBILE_PLAN_DIALOG.onClickListener id=" + id); - mManageMobilePlanMessage = null; - } - }) - .create(); + .setMessage(mMobilePlanPreferenceController.getMobilePlanDialogMessage()) + .setCancelable(false) + .setPositiveButton(com.android.internal.R.string.ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + log("MANAGE_MOBILE_PLAN_DIALOG.onClickListener id=" + id); + mMobilePlanPreferenceController + .setMobilePlanDialogMessage(null); + } + }) + .create(); } return super.onCreateDialog(dialogId); } @@ -215,13 +142,6 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (savedInstanceState != null) { - mManageMobilePlanMessage = savedInstanceState.getString(SAVED_MANAGE_MOBILE_PLAN_MSG); - } - log("onCreate: mManageMobilePlanMessage=" + mManageMobilePlanMessage); - - mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); - mTm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); mUm = (UserManager) getSystemService(Context.USER_SERVICE); addPreferencesFromResource(R.xml.wireless_settings); @@ -235,11 +155,21 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde mTetherPreferenceController = new TetherPreferenceController(activity); mMobileNetworkPreferenceController = new MobileNetworkPreferenceController(activity); mVpnPreferenceController = new VpnPreferenceController(activity); + mWifiCallingPreferenceController = new WifiCallingPreferenceController(activity); + mNetworkResetPreferenceController = new NetworkResetPreferenceController(activity); + mProxyPreferenceController = new ProxyPreferenceController(activity); + mMobilePlanPreferenceController = new MobilePlanPreferenceController(activity, this); + + mMobilePlanPreferenceController.onCreate(savedInstanceState); mAirplaneModePreferenceController.displayPreference(screen); mTetherPreferenceController.displayPreference(screen); mMobileNetworkPreferenceController.displayPreference(screen); mVpnPreferenceController.displayPreference(screen); + mWifiCallingPreferenceController.displayPreference(screen); + mNetworkResetPreferenceController.displayPreference(screen); + mProxyPreferenceController.displayPreference(screen); + mMobilePlanPreferenceController.displayPreference(screen); SwitchPreference nfc = (SwitchPreference) findPreference(KEY_TOGGLE_NFC); RestrictedPreference androidBeam = (RestrictedPreference) findPreference( @@ -247,8 +177,6 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde mNfcEnabler = new NfcEnabler(activity, nfc, androidBeam); - mButtonWfc = (PreferenceScreen) findPreference(KEY_WFC_SETTINGS); - String toggleable = Settings.Global.getString(activity.getContentResolver(), Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); @@ -261,7 +189,7 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde Preference ps = findPreference(KEY_WIMAX_SETTINGS); if (ps != null) root.removePreference(ps); } else { - if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIMAX ) + if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_WIMAX) && isWimaxEnabled) { Preference ps = findPreference(KEY_WIMAX_SETTINGS); ps.setDependency(AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE); @@ -283,38 +211,6 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde getPreferenceScreen().removePreference(androidBeam); mNfcEnabler = null; } - - // Remove Mobile Network Settings and Manage Mobile Plan for secondary users, - // if it's a wifi-only device. - if (!isAdmin || Utils.isWifiOnly(getActivity()) || - RestrictedLockUtils.hasBaseUserRestriction(activity, - UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, UserHandle.myUserId())) { - removePreference(KEY_MANAGE_MOBILE_PLAN); - } - // Remove Mobile Network Settings and Manage Mobile Plan - // if config_show_mobile_plan sets false. - final boolean isMobilePlanEnabled = this.getResources().getBoolean( - R.bool.config_show_mobile_plan); - if (!isMobilePlanEnabled) { - Preference pref = findPreference(KEY_MANAGE_MOBILE_PLAN); - if (pref != null) { - removePreference(KEY_MANAGE_MOBILE_PLAN); - } - } - - // Enable Proxy selector settings if allowed. - Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS); - final DevicePolicyManager mDPM = (DevicePolicyManager) - activity.getSystemService(Context.DEVICE_POLICY_SERVICE); - // proxy UI disabled until we have better app support - getPreferenceScreen().removePreference(mGlobalProxy); - mGlobalProxy.setEnabled(mDPM.getGlobalProxyAdmin() == null); - - // Remove network reset if not allowed - if (RestrictedLockUtils.hasBaseUserRestriction(activity, - UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) { - removePreference(KEY_NETWORK_RESET); - } } @Override @@ -325,27 +221,12 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde if (mNfcEnabler != null) { mNfcEnabler.resume(); } - - // update WFC setting - final Context context = getActivity(); - if (ImsManager.isWfcEnabledByPlatform(context) && - ImsManager.isWfcProvisionedOnDevice(context)) { - getPreferenceScreen().addPreference(mButtonWfc); - - mButtonWfc.setSummary(WifiCallingSettings.getWfcModeSummary( - context, ImsManager.getWfcMode(context, mTm.isNetworkRoaming()))); - } else { - removePreference(KEY_WFC_SETTINGS); - } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - - if (!TextUtils.isEmpty(mManageMobilePlanMessage)) { - outState.putString(SAVED_MANAGE_MOBILE_PLAN_MSG, mManageMobilePlanMessage); - } + mMobilePlanPreferenceController.onSaveInstanceState(outState); } @Override @@ -363,6 +244,11 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde super.onActivityResult(requestCode, resultCode, data); } + @Override + public void showMobilePlanMessageDialog() { + showDialog(MANAGE_MOBILE_PLAN_DIALOG_ID); + } + @Override protected int getHelpResource() { return R.string.help_url_more_networks; @@ -372,79 +258,60 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde * For Search. */ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider() { - @Override - public List getXmlResourcesToIndex( - Context context, boolean enabled) { - // Remove wireless settings from search in demo mode - if (UserManager.isDeviceInDemoMode(context)) { - return Collections.emptyList(); - } - SearchIndexableResource sir = new SearchIndexableResource(context); - sir.xmlResId = R.xml.wireless_settings; - return Arrays.asList(sir); - } - - @Override - public List getNonIndexableKeys(Context context) { - final ArrayList result = new ArrayList(); - - final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); - final boolean isSecondaryUser = !um.isAdminUser(); - final boolean isWimaxEnabled = !isSecondaryUser - && context.getResources().getBoolean( - com.android.internal.R.bool.config_wimaxEnabled); - if (!isWimaxEnabled) { - result.add(KEY_WIMAX_SETTINGS); - } - - new VpnPreferenceController(context).updateNonIndexableKeys(result); - - // Remove NFC if not available - final NfcManager manager = (NfcManager) - context.getSystemService(Context.NFC_SERVICE); - if (manager != null) { - NfcAdapter adapter = manager.getDefaultAdapter(); - if (adapter == null) { - result.add(KEY_TOGGLE_NFC); - result.add(KEY_ANDROID_BEAM_SETTINGS); + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex( + Context context, boolean enabled) { + // Remove wireless settings from search in demo mode + if (UserManager.isDeviceInDemoMode(context)) { + return Collections.emptyList(); } + SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.wireless_settings; + return Arrays.asList(sir); } - // Remove Mobile Network Settings and Manage Mobile Plan if it's a wifi-only device. - if (isSecondaryUser || Utils.isWifiOnly(context)) { - result.add(KEY_MANAGE_MOBILE_PLAN); + @Override + public List getNonIndexableKeys(Context context) { + final ArrayList result = new ArrayList(); + + final UserManager um = (UserManager) context.getSystemService( + Context.USER_SERVICE); + final boolean isSecondaryUser = !um.isAdminUser(); + final boolean isWimaxEnabled = !isSecondaryUser + && context.getResources().getBoolean( + com.android.internal.R.bool.config_wimaxEnabled); + if (!isWimaxEnabled) { + result.add(KEY_WIMAX_SETTINGS); + } + + new VpnPreferenceController(context).updateNonIndexableKeys(result); + + // Remove NFC if not available + final NfcManager manager = (NfcManager) + context.getSystemService(Context.NFC_SERVICE); + if (manager != null) { + NfcAdapter adapter = manager.getDefaultAdapter(); + if (adapter == null) { + result.add(KEY_TOGGLE_NFC); + result.add(KEY_ANDROID_BEAM_SETTINGS); + } + } + new MobilePlanPreferenceController(context, null /* MobilePlanClickHandler */) + .updateNonIndexableKeys(result); + new MobileNetworkPreferenceController(context).updateNonIndexableKeys(result); + + // Remove Airplane Mode settings if it's a stationary device such as a TV. + new AirplaneModePreferenceController(context, null /* fragment */) + .updateNonIndexableKeys(result); + + new ProxyPreferenceController(context).updateNonIndexableKeys(result); + + new TetherPreferenceController(context).updateNonIndexableKeys(result); + new WifiCallingPreferenceController(context).updateNonIndexableKeys(result); + new NetworkResetPreferenceController(context).updateNonIndexableKeys(result); + + return result; } - new MobileNetworkPreferenceController(context).updateNonIndexableKeys(result); - - // Remove Mobile Network Settings and Manage Mobile Plan - // if config_show_mobile_plan sets false. - final boolean isMobilePlanEnabled = context.getResources().getBoolean( - R.bool.config_show_mobile_plan); - if (!isMobilePlanEnabled) { - result.add(KEY_MANAGE_MOBILE_PLAN); - } - // Remove Airplane Mode settings if it's a stationary device such as a TV. - new AirplaneModePreferenceController(context, null /* fragment */) - .updateNonIndexableKeys(result); - - // proxy UI disabled until we have better app support - result.add(KEY_PROXY_SETTINGS); - - new TetherPreferenceController(context) - .updateNonIndexableKeys(result); - - if (!ImsManager.isWfcEnabledByPlatform(context) || - !ImsManager.isWfcProvisionedOnDevice(context)) { - result.add(KEY_WFC_SETTINGS); - } - - if (RestrictedLockUtils.hasBaseUserRestriction(context, - UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) { - result.add(KEY_NETWORK_RESET); - } - - return result; - } - }; + }; } diff --git a/src/com/android/settings/core/lifecycle/Lifecycle.java b/src/com/android/settings/core/lifecycle/Lifecycle.java index c1d6457dd20..c47f97ed718 100644 --- a/src/com/android/settings/core/lifecycle/Lifecycle.java +++ b/src/com/android/settings/core/lifecycle/Lifecycle.java @@ -17,11 +17,14 @@ package com.android.settings.core.lifecycle; import android.annotation.UiThread; import android.content.Context; +import android.os.Bundle; import com.android.settings.core.lifecycle.events.OnAttach; +import com.android.settings.core.lifecycle.events.OnCreate; import com.android.settings.core.lifecycle.events.OnDestroy; import com.android.settings.core.lifecycle.events.OnPause; import com.android.settings.core.lifecycle.events.OnResume; +import com.android.settings.core.lifecycle.events.OnSaveInstanceState; import com.android.settings.core.lifecycle.events.OnStart; import com.android.settings.core.lifecycle.events.OnStop; import com.android.settings.utils.ThreadUtils; @@ -54,6 +57,14 @@ public class Lifecycle { } } + public void onCreate(Bundle savedInstanceState) { + for (LifecycleObserver observer : mObservers) { + if (observer instanceof OnCreate) { + ((OnCreate) observer).onCreate(savedInstanceState); + } + } + } + public void onStart() { for (LifecycleObserver observer : mObservers) { if (observer instanceof OnStart) { @@ -78,6 +89,14 @@ public class Lifecycle { } } + public void onSaveInstanceState(Bundle outState) { + for (LifecycleObserver observer : mObservers) { + if (observer instanceof OnSaveInstanceState) { + ((OnSaveInstanceState) observer).onSaveInstanceState(outState); + } + } + } + public void onStop() { for (LifecycleObserver observer : mObservers) { if (observer instanceof OnStop) { diff --git a/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java b/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java index dff1d8f76ee..e9822af1c04 100644 --- a/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java +++ b/src/com/android/settings/core/lifecycle/ObservablePreferenceFragment.java @@ -18,6 +18,7 @@ package com.android.settings.core.lifecycle; import android.annotation.CallSuper; import android.content.Context; +import android.os.Bundle; import android.support.v14.preference.PreferenceFragment; /** @@ -38,6 +39,20 @@ public abstract class ObservablePreferenceFragment extends PreferenceFragment { mLifecycle.onAttach(context); } + @CallSuper + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mLifecycle.onCreate(savedInstanceState); + } + + @CallSuper + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mLifecycle.onSaveInstanceState(outState); + } + @CallSuper @Override public void onStart() { diff --git a/src/com/android/settings/core/lifecycle/events/OnCreate.java b/src/com/android/settings/core/lifecycle/events/OnCreate.java new file mode 100644 index 00000000000..9c97cf5f239 --- /dev/null +++ b/src/com/android/settings/core/lifecycle/events/OnCreate.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 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.core.lifecycle.events; + + +import android.os.Bundle; + +public interface OnCreate { + void onCreate(Bundle savedInstanceState); +} diff --git a/src/com/android/settings/core/lifecycle/events/OnSaveInstanceState.java b/src/com/android/settings/core/lifecycle/events/OnSaveInstanceState.java new file mode 100644 index 00000000000..fab4041f9a9 --- /dev/null +++ b/src/com/android/settings/core/lifecycle/events/OnSaveInstanceState.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 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.core.lifecycle.events; + +import android.os.Bundle; + + +public interface OnSaveInstanceState { + void onSaveInstanceState(Bundle outState); +} diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java index 3905ca678d2..509c7711bf7 100644 --- a/src/com/android/settings/network/MobileNetworkPreferenceController.java +++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java @@ -46,9 +46,9 @@ public class MobileNetworkPreferenceController extends PreferenceController { @Override protected boolean isAvailable() { - return mIsSecondaryUser - || Utils.isWifiOnly(mContext) - || hasBaseUserRestriction(mContext, DISALLOW_CONFIG_MOBILE_NETWORKS, myUserId()); + return !mIsSecondaryUser + && !Utils.isWifiOnly(mContext) + && !hasBaseUserRestriction(mContext, DISALLOW_CONFIG_MOBILE_NETWORKS, myUserId()); } @Override diff --git a/src/com/android/settings/network/MobilePlanPreferenceController.java b/src/com/android/settings/network/MobilePlanPreferenceController.java new file mode 100644 index 00000000000..e62686fa119 --- /dev/null +++ b/src/com/android/settings/network/MobilePlanPreferenceController.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2016 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; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.Uri; +import android.os.Bundle; +import android.os.UserManager; +import android.support.v7.preference.Preference; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.telephony.TelephonyIntents; +import com.android.settings.R; +import com.android.settings.Utils; +import com.android.settings.core.PreferenceController; +import com.android.settings.core.lifecycle.LifecycleObserver; +import com.android.settings.core.lifecycle.events.OnCreate; +import com.android.settings.core.lifecycle.events.OnSaveInstanceState; + +import java.util.List; + +import static android.content.Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.os.UserHandle.myUserId; +import static android.os.UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS; +import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction; + + +public class MobilePlanPreferenceController extends PreferenceController implements + LifecycleObserver, OnCreate, OnSaveInstanceState { + + public interface MobilePlanPreferenceHost { + void showMobilePlanMessageDialog(); + } + + public static final int MANAGE_MOBILE_PLAN_DIALOG_ID = 1; + + private static final String TAG = "MobilePlanPrefContr"; + private static final String KEY_MANAGE_MOBILE_PLAN = "manage_mobile_plan"; + private static final String SAVED_MANAGE_MOBILE_PLAN_MSG = "mManageMobilePlanMessage"; + + private final UserManager mUserManager; + private final boolean mIsSecondaryUser; + private final MobilePlanPreferenceHost mHost; + + private ConnectivityManager mCm; + private TelephonyManager mTm; + + private String mMobilePlanDialogMessage; + + public MobilePlanPreferenceController(Context context, + MobilePlanPreferenceHost host) { + super(context); + mHost = host; + mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + mTm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mIsSecondaryUser = !mUserManager.isAdminUser(); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (mHost != null && KEY_MANAGE_MOBILE_PLAN.equals(preference.getKey())) { + mMobilePlanDialogMessage = null; + onManageMobilePlanClick(); + } + return false; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + if (savedInstanceState != null) { + mMobilePlanDialogMessage = savedInstanceState.getString(SAVED_MANAGE_MOBILE_PLAN_MSG); + } + Log.d(TAG, "onCreate: mMobilePlanDialogMessage=" + mMobilePlanDialogMessage); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + if (!TextUtils.isEmpty(mMobilePlanDialogMessage)) { + outState.putString(SAVED_MANAGE_MOBILE_PLAN_MSG, mMobilePlanDialogMessage); + } + } + + public String getMobilePlanDialogMessage() { + return mMobilePlanDialogMessage; + } + + public void setMobilePlanDialogMessage(String messasge) { + mMobilePlanDialogMessage = messasge; + } + + @Override + protected boolean isAvailable() { + final boolean isPrefAllowedOnDevice = mContext.getResources().getBoolean( + com.android.settings.R.bool.config_show_mobile_plan); + final boolean isPrefAllowedForUser = !mIsSecondaryUser + && !Utils.isWifiOnly(mContext) + && !hasBaseUserRestriction(mContext, DISALLOW_CONFIG_MOBILE_NETWORKS, myUserId()); + return isPrefAllowedForUser && isPrefAllowedOnDevice; + } + @Override + protected String getPreferenceKey() { + return KEY_MANAGE_MOBILE_PLAN; + } + + private void onManageMobilePlanClick() { + Resources resources = mContext.getResources(); + NetworkInfo ni = mCm.getActiveNetworkInfo(); + if (mTm.hasIccCard() && (ni != null)) { + // Check for carrier apps that can handle provisioning first + Intent provisioningIntent = new Intent(TelephonyIntents.ACTION_CARRIER_SETUP); + List carrierPackages = + mTm.getCarrierPackageNamesForIntent(provisioningIntent); + if (carrierPackages != null && !carrierPackages.isEmpty()) { + if (carrierPackages.size() != 1) { + Log.w(TAG, "Multiple matching carrier apps found, launching the first."); + } + provisioningIntent.setPackage(carrierPackages.get(0)); + mContext.startActivity(provisioningIntent); + return; + } + + // Get provisioning URL + String url = mCm.getMobileProvisioningUrl(); + if (!TextUtils.isEmpty(url)) { + Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, + Intent.CATEGORY_APP_BROWSER); + intent.setData(Uri.parse(url)); + intent.setFlags(FLAG_ACTIVITY_BROUGHT_TO_FRONT | FLAG_ACTIVITY_NEW_TASK); + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.w(TAG, "onManageMobilePlanClick: startActivity failed" + e); + } + } else { + // No provisioning URL + String operatorName = mTm.getSimOperatorName(); + if (TextUtils.isEmpty(operatorName)) { + // Use NetworkOperatorName as second choice in case there is no + // SPN (Service Provider Name on the SIM). Such as with T-mobile. + operatorName = mTm.getNetworkOperatorName(); + if (TextUtils.isEmpty(operatorName)) { + mMobilePlanDialogMessage = + resources.getString(R.string.mobile_unknown_sim_operator); + } else { + mMobilePlanDialogMessage = resources.getString( + R.string.mobile_no_provisioning_url, operatorName); + } + } else { + mMobilePlanDialogMessage = + resources.getString(R.string.mobile_no_provisioning_url, operatorName); + } + } + } else if (mTm.hasIccCard() == false) { + // No sim card + mMobilePlanDialogMessage = resources.getString(R.string.mobile_insert_sim_card); + } else { + // NetworkInfo is null, there is no connection + mMobilePlanDialogMessage = resources.getString(R.string.mobile_connect_to_internet); + } + if (!TextUtils.isEmpty(mMobilePlanDialogMessage)) { + Log.d(TAG, "onManageMobilePlanClick: message=" + mMobilePlanDialogMessage); + if (mHost != null) { + mHost.showMobilePlanMessageDialog(); + } else { + Log.d(TAG, "Missing host fragment, cannot show message dialog."); + } + } + } +} diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java index 88099c66a82..fca8ec72f4e 100644 --- a/src/com/android/settings/network/NetworkDashboardFragment.java +++ b/src/com/android/settings/network/NetworkDashboardFragment.java @@ -15,8 +15,12 @@ */ package com.android.settings.network; +import android.app.AlertDialog; +import android.app.Dialog; import android.content.Context; +import android.util.Log; +import com.android.internal.logging.MetricsProto; import com.android.settings.R; import com.android.settings.core.PreferenceController; import com.android.settings.dashboard.DashboardFragment; @@ -25,7 +29,11 @@ import com.android.settingslib.drawer.CategoryKey; import java.util.ArrayList; import java.util.List; -public class NetworkDashboardFragment extends DashboardFragment { +import static com.android.settings.network.MobilePlanPreferenceController + .MANAGE_MOBILE_PLAN_DIALOG_ID; + +public class NetworkDashboardFragment extends DashboardFragment implements + MobilePlanPreferenceController.MobilePlanPreferenceHost { private static final String TAG = "NetworkDashboardFrag"; @@ -53,13 +61,50 @@ public class NetworkDashboardFragment extends DashboardFragment { protected List getPreferenceControllers(Context context) { final AirplaneModePreferenceController airplaneModePreferenceController = new AirplaneModePreferenceController(context, this /* fragment */); + final MobilePlanPreferenceController mobilePlanPreferenceController = + new MobilePlanPreferenceController(context, this); getLifecycle().addObserver(airplaneModePreferenceController); + getLifecycle().addObserver(mobilePlanPreferenceController); final List controllers = new ArrayList<>(); controllers.add(airplaneModePreferenceController); - controllers.add(new TetherPreferenceController(context)); controllers.add(new MobileNetworkPreferenceController(context)); + controllers.add(new TetherPreferenceController(context)); controllers.add(new VpnPreferenceController(context)); + controllers.add(new WifiCallingPreferenceController(context)); + controllers.add(new NetworkResetPreferenceController(context)); + controllers.add(new ProxyPreferenceController(context)); + controllers.add(mobilePlanPreferenceController); return controllers; } + + @Override + public void showMobilePlanMessageDialog() { + showDialog(MANAGE_MOBILE_PLAN_DIALOG_ID); + } + + @Override + public Dialog onCreateDialog(int dialogId) { + Log.d(TAG, "onCreateDialog: dialogId=" + dialogId); + switch (dialogId) { + case MANAGE_MOBILE_PLAN_DIALOG_ID: + final MobilePlanPreferenceController controller = + getPreferenceController(MobilePlanPreferenceController.class); + return new AlertDialog.Builder(getActivity()) + .setMessage(controller.getMobilePlanDialogMessage()) + .setCancelable(false) + .setPositiveButton(com.android.internal.R.string.ok, + (dialog, id) -> controller.setMobilePlanDialogMessage(null)) + .create(); + } + return super.onCreateDialog(dialogId); + } + + @Override + public int getDialogMetricsCategory(int dialogId) { + if (MANAGE_MOBILE_PLAN_DIALOG_ID == dialogId) { + return MetricsProto.MetricsEvent.DIALOG_MANAGE_MOBILE_PLAN; + } + return 0; + } } diff --git a/src/com/android/settings/network/NetworkResetPreferenceController.java b/src/com/android/settings/network/NetworkResetPreferenceController.java new file mode 100644 index 00000000000..2fe2038afe8 --- /dev/null +++ b/src/com/android/settings/network/NetworkResetPreferenceController.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 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; + +import android.content.Context; +import android.os.UserHandle; +import android.os.UserManager; +import android.support.v7.preference.Preference; + +import com.android.settings.core.PreferenceController; +import com.android.settingslib.RestrictedLockUtils; + +public class NetworkResetPreferenceController extends PreferenceController { + + private static final String KEY_NETWORK_RESET = "network_reset"; + + public NetworkResetPreferenceController(Context context) { + super(context); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + protected boolean isAvailable() { + return !RestrictedLockUtils.hasBaseUserRestriction(mContext, + UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId()); + } + + @Override + protected String getPreferenceKey() { + return KEY_NETWORK_RESET; + } +} diff --git a/src/com/android/settings/network/ProxyPreferenceController.java b/src/com/android/settings/network/ProxyPreferenceController.java new file mode 100644 index 00000000000..075b1f0555d --- /dev/null +++ b/src/com/android/settings/network/ProxyPreferenceController.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 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; + +import android.app.admin.DevicePolicyManager; +import android.content.Context; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.core.PreferenceController; + +public class ProxyPreferenceController extends PreferenceController { + + private static final String KEY_PROXY_SETTINGS = "proxy_settings"; + + public ProxyPreferenceController(Context context) { + super(context); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + protected boolean isAvailable() { + // proxy UI disabled until we have better app support + return false; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + // Enable Proxy selector settings if allowed. + final Preference pref = screen.findPreference(KEY_PROXY_SETTINGS); + if (pref != null) { + final DevicePolicyManager dpm = (DevicePolicyManager) + mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); + pref.setEnabled(dpm.getGlobalProxyAdmin() == null); + } + } + + @Override + protected String getPreferenceKey() { + return KEY_PROXY_SETTINGS; + } +} diff --git a/src/com/android/settings/network/WifiCallingPreferenceController.java b/src/com/android/settings/network/WifiCallingPreferenceController.java new file mode 100644 index 00000000000..e733b670a7e --- /dev/null +++ b/src/com/android/settings/network/WifiCallingPreferenceController.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 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; + +import android.content.Context; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; +import android.telephony.TelephonyManager; + +import com.android.ims.ImsManager; +import com.android.settings.WifiCallingSettings; +import com.android.settings.core.PreferenceController; + +public class WifiCallingPreferenceController extends PreferenceController { + + private static final String KEY_WFC_SETTINGS = "wifi_calling_settings"; + private TelephonyManager mTm; + + public WifiCallingPreferenceController(Context context) { + super(context); + mTm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + final Preference pref = screen.findPreference(KEY_WFC_SETTINGS); + if (pref != null) { + pref.setSummary(WifiCallingSettings.getWfcModeSummary( + mContext, ImsManager.getWfcMode(mContext, mTm.isNetworkRoaming()))); + } + } + + @Override + protected boolean isAvailable() { + return ImsManager.isWfcEnabledByPlatform(mContext) + && ImsManager.isWfcProvisionedOnDevice(mContext); + } + + @Override + protected String getPreferenceKey() { + return KEY_WFC_SETTINGS; + } +} diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java new file mode 100644 index 00000000000..0adfea81d7d --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2016 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; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.os.UserHandle; +import android.os.UserManager; + +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class MobileNetworkPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private UserManager mUserManager; + @Mock + private ConnectivityManager mConnectivityManager; + + private MobileNetworkPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)) + .thenReturn(mConnectivityManager); + } + + @Test + public void secondaryUser_prefIsNotAvailable() { + when(mUserManager.isAdminUser()).thenReturn(false); + when(mUserManager.hasUserRestriction(anyString(), any(UserHandle.class))) + .thenReturn(false); + when(mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) + .thenReturn(true); + + mController = new MobileNetworkPreferenceController(mContext); + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void wifiOnly_prefIsNotAvailable() { + when(mUserManager.isAdminUser()).thenReturn(true); + when(mUserManager.hasUserRestriction(anyString(), any(UserHandle.class))) + .thenReturn(false); + when(mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) + .thenReturn(false); + + mController = new MobileNetworkPreferenceController(mContext); + assertThat(mController.isAvailable()).isFalse(); + } +}