diff --git a/res/values/strings.xml b/res/values/strings.xml index 8347f9956c9..0797fe6e96f 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -402,11 +402,6 @@ Allow your phone to communicate with nearby Bluetooth devices - - Disable in-band ringing - - Don’t play custom phone ringtones on Bluetooth headsets - Available media devices @@ -1691,15 +1686,10 @@ Remember settings - Maximum connected Bluetooth audio devices Select maximum number of connected Bluetooth audio devices - - Disable Bluetooth AVDTP delay reports - - Disallow receiving Bluetooth AVDTP delay reports Cast @@ -2350,6 +2340,17 @@ Learn more about Private DNS features + + Setting managed by carrier + + Activate Wi\u2011Fi Calling + + Turn on Wi\u2011Fi calling + + Wi\u2011Fi calling is not supported for %1$s + + Carrier Display @@ -4922,6 +4923,8 @@ Limit background activity? If you limit background activity for an app, it may misbehave + + Since this app is not set to optimize battery, you can\u2019t restrict it.\n\nTo restrict the app, first turn on battery optimization. Screen usage since full charge @@ -7930,6 +7933,9 @@ Calls + + Allow calls + When Do Not Disturb is on, incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you. @@ -7945,6 +7951,9 @@ Messages + + Allow messages + Messages @@ -7984,9 +7993,15 @@ Reminders + + Allow reminders + Events + + Allow events + anyone @@ -7999,8 +8014,11 @@ Repeat callers + + Allow repeat callers + - From %1$s only + From %1$s From %1$s and %2$s diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml index c491980153c..3836b43930b 100644 --- a/res/xml/development_settings.xml +++ b/res/xml/development_settings.xml @@ -254,16 +254,6 @@ android:title="@string/bluetooth_disable_absolute_volume" android:summary="@string/bluetooth_disable_absolute_volume_summary" /> - - - - + android:positiveButtonText="@string/save" + android:negativeButtonText="@android:string/cancel" /> diff --git a/res/xml/zen_mode_calls_settings.xml b/res/xml/zen_mode_calls_settings.xml index 62d9ef4490d..1a6655ffde6 100644 --- a/res/xml/zen_mode_calls_settings.xml +++ b/res/xml/zen_mode_calls_settings.xml @@ -25,7 +25,7 @@ @@ -36,7 +36,7 @@ + android:title="@string/zen_mode_repeat_callers_title" /> diff --git a/res/xml/zen_mode_msg_event_reminder_settings.xml b/res/xml/zen_mode_msg_event_reminder_settings.xml index 2f065a6e881..9bee9e94483 100644 --- a/res/xml/zen_mode_msg_event_reminder_settings.xml +++ b/res/xml/zen_mode_msg_event_reminder_settings.xml @@ -25,7 +25,7 @@ @@ -36,12 +36,12 @@ + android:title="@string/zen_mode_reminders_title"/> + android:title="@string/zen_mode_events_title"/> diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index 94c3fb581fa..1e56e540dcc 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -387,7 +387,6 @@ public class TetherSettings extends RestrictedSettingsFragment if (adapter.getState() == BluetoothAdapter.STATE_OFF) { mBluetoothEnableForTether = true; adapter.enable(); - mBluetoothTether.setSummary(R.string.bluetooth_turning_on); mBluetoothTether.setEnabled(false); return; } diff --git a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java index c8e6f26038f..01c1ff61832 100644 --- a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java +++ b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java @@ -25,11 +25,13 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback; import com.android.settings.dashboard.DashboardFragment; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.CachedBluetoothDevice; +import android.support.v7.preference.Preference; /** * Controller to maintain available media Bluetooth devices */ -public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater { +public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater + implements Preference.OnPreferenceClickListener { private static final String TAG = "AvailableMediaBluetoothDeviceUpdater"; private static final boolean DBG = false; @@ -116,5 +118,12 @@ public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater } return isFilterMatched; } + + @Override + public boolean onPreferenceClick(Preference preference) { + final CachedBluetoothDevice device = ((BluetoothDevicePreference) preference) + .getBluetoothDevice(); + return device.setActive(); + } } diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java index 8937b177a64..bab71713a2a 100644 --- a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java +++ b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java @@ -59,24 +59,12 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback, protected DashboardFragment mFragment; private final boolean mShowDeviceWithoutNames; - private Preference.OnPreferenceClickListener mDevicePreferenceClickListener = null; - + @VisibleForTesting final GearPreference.OnGearClickListener mDeviceProfilesListener = pref -> { launchDeviceDetails(pref); }; - private class PreferenceClickListener implements - Preference.OnPreferenceClickListener { - @Override - public boolean onPreferenceClick(Preference preference) { - final CachedBluetoothDevice device = - ((BluetoothDevicePreference) preference).getBluetoothDevice(); - Log.i(TAG, "OnPreferenceClickListener: device=" + device); - return device.setActive(); - } - } - public BluetoothDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback) { this(fragment, devicePreferenceCallback, Utils.getLocalBtManager(context)); @@ -91,7 +79,6 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback, BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false); mPreferenceMap = new HashMap<>(); mLocalManager = localManager; - mDevicePreferenceClickListener = new PreferenceClickListener(); } /** @@ -212,7 +199,10 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback, new BluetoothDevicePreference(mPrefContext, cachedDevice, mShowDeviceWithoutNames); btPreference.setOnGearClickListener(mDeviceProfilesListener); - btPreference.setOnPreferenceClickListener(mDevicePreferenceClickListener); + if (this instanceof Preference.OnPreferenceClickListener) { + btPreference.setOnPreferenceClickListener( + (Preference.OnPreferenceClickListener)this); + } mPreferenceMap.put(device, btPreference); mDevicePreferenceCallback.onDeviceAdded(btPreference); } diff --git a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java index 34cb5746c60..f087c6ac7d3 100644 --- a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java +++ b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java @@ -24,11 +24,15 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback; import com.android.settings.dashboard.DashboardFragment; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; +import android.support.v7.preference.Preference; +import android.util.Log; /** * Maintain and update saved bluetooth devices(bonded but not connected) */ -public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater { +public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater + implements Preference.OnPreferenceClickListener { + private static final String TAG = "SavedBluetoothDeviceUpdater"; public SavedBluetoothDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback) { @@ -57,4 +61,12 @@ public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater { final BluetoothDevice device = cachedDevice.getDevice(); return device.getBondState() == BluetoothDevice.BOND_BONDED && !device.isConnected(); } + + @Override + public boolean onPreferenceClick(Preference preference) { + final CachedBluetoothDevice device = ((BluetoothDevicePreference) preference) + .getBluetoothDevice(); + device.connect(true); + return true; + } } diff --git a/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java b/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java deleted file mode 100644 index 6c7a7dd9643..00000000000 --- a/src/com/android/settings/development/BluetoothDelayReportsPreferenceController.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.development; - -import android.content.Context; -import android.os.SystemProperties; -import android.support.annotation.VisibleForTesting; -import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.Preference; - -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settingslib.development.DeveloperOptionsPreferenceController; - -public class BluetoothDelayReportsPreferenceController extends DeveloperOptionsPreferenceController - implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { - - private static final String BLUETOOTH_DISABLE_AVDTP_DELAY_REPORT_KEY = - "bluetooth_disable_avdtp_delay_reports"; - @VisibleForTesting - static final String BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY = - "persist.bluetooth.disabledelayreports"; - - public BluetoothDelayReportsPreferenceController(Context context) { - super(context); - } - - @Override - public String getPreferenceKey() { - return BLUETOOTH_DISABLE_AVDTP_DELAY_REPORT_KEY; - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean isDisabled = (Boolean) newValue; - SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, - isDisabled ? "true" : "false"); - return true; - } - - @Override - public void updateState(Preference preference) { - final boolean isDisabled = SystemProperties.getBoolean( - BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */); - ((SwitchPreference) mPreference).setChecked(isDisabled); - } - - @Override - protected void onDeveloperOptionsSwitchDisabled() { - super.onDeveloperOptionsSwitchDisabled(); - // the default setting for this preference is the disabled state - ((SwitchPreference) mPreference).setChecked(false); - SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, "false"); - } - -} diff --git a/src/com/android/settings/development/BluetoothInbandRingingPreferenceController.java b/src/com/android/settings/development/BluetoothInbandRingingPreferenceController.java deleted file mode 100644 index c64ac111ecd..00000000000 --- a/src/com/android/settings/development/BluetoothInbandRingingPreferenceController.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.development; - -import android.bluetooth.BluetoothHeadset; -import android.content.Context; -import android.os.SystemProperties; -import android.support.annotation.VisibleForTesting; -import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.Preference; - -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settingslib.development.DeveloperOptionsPreferenceController; - -public class BluetoothInbandRingingPreferenceController extends DeveloperOptionsPreferenceController - implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { - - private static final String BLUETOOTH_DISABLE_INBAND_RINGING_KEY = - "bluetooth_disable_inband_ringing"; - @VisibleForTesting - static final String BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY = - "persist.bluetooth.disableinbandringing"; - - public BluetoothInbandRingingPreferenceController(Context context) { - super(context); - } - - @Override - public boolean isAvailable() { - return isInbandRingingSupported(); - } - - @Override - public String getPreferenceKey() { - return BLUETOOTH_DISABLE_INBAND_RINGING_KEY; - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean isChecked = (Boolean) newValue; - SystemProperties.set(BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY, - isChecked ? "true" : "false"); - return true; - } - - @Override - public void updateState(Preference preference) { - final boolean isEnabled = SystemProperties.getBoolean( - BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY, false /* default */); - ((SwitchPreference) mPreference).setChecked(isEnabled); - } - - @Override - protected void onDeveloperOptionsSwitchDisabled() { - super.onDeveloperOptionsSwitchDisabled(); - ((SwitchPreference) mPreference).setChecked(false); - SystemProperties.set(BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY, "false"); - } - - @VisibleForTesting - boolean isInbandRingingSupported() { - return BluetoothHeadset.isInbandRingingSupported(mContext); - } -} diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index 3ee5db1df74..5f5d1a83c7d 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -404,8 +404,6 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra controllers.add(new TetheringHardwareAccelPreferenceController(context)); controllers.add(new BluetoothDeviceNoNamePreferenceController(context)); controllers.add(new BluetoothAbsoluteVolumePreferenceController(context)); - controllers.add(new BluetoothInbandRingingPreferenceController(context)); - controllers.add(new BluetoothDelayReportsPreferenceController(context)); controllers.add(new BluetoothAvrcpVersionPreferenceController(context)); controllers.add(new BluetoothAudioCodecPreferenceController(context, lifecycle, bluetoothA2dpConfigStore)); diff --git a/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java b/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java index ca4742d1fcb..3075d9bf0ea 100644 --- a/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java +++ b/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java @@ -21,9 +21,14 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.PowerManager; +import android.support.annotation.IntDef; import android.support.annotation.VisibleForTesting; import com.android.settings.Utils; +import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Use this broadcastReceiver to listen to the battery change, and it will invoke @@ -43,7 +48,19 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver { * Battery saver(e.g. off->on) */ public interface OnBatteryChangedListener { - void onBatteryChanged(); + void onBatteryChanged(@BatteryUpdateType int type); + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef({BatteryUpdateType.MANUAL, + BatteryUpdateType.BATTERY_LEVEL, + BatteryUpdateType.BATTERY_SAVER, + BatteryUpdateType.BATTERY_STATUS}) + public @interface BatteryUpdateType { + int MANUAL = 0; + int BATTERY_LEVEL = 1; + int BATTERY_SAVER = 2; + int BATTERY_STATUS = 3; } @VisibleForTesting @@ -85,14 +102,17 @@ public class BatteryBroadcastReceiver extends BroadcastReceiver { final String batteryLevel = Utils.getBatteryPercentage(intent); final String batteryStatus = Utils.getBatteryStatus( mContext.getResources(), intent); - if (forceUpdate || !batteryLevel.equals(mBatteryLevel) || !batteryStatus.equals( - mBatteryStatus)) { - mBatteryLevel = batteryLevel; - mBatteryStatus = batteryStatus; - mBatteryListener.onBatteryChanged(); + if (forceUpdate) { + mBatteryListener.onBatteryChanged(BatteryUpdateType.MANUAL); + } else if(!batteryLevel.equals(mBatteryLevel)) { + mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_LEVEL); + } else if (!batteryStatus.equals(mBatteryStatus)) { + mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_STATUS); } + mBatteryLevel = batteryLevel; + mBatteryStatus = batteryStatus; } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) { - mBatteryListener.onBatteryChanged(); + mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_SAVER); } } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java index 327a6c58bfa..64934308820 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java +++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java @@ -13,6 +13,8 @@ */ package com.android.settings.fuelgauge; +import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType; + import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -30,7 +32,6 @@ import com.android.settings.SettingsActivity; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.utils.StringUtil; import java.util.ArrayList; import java.util.Arrays; @@ -106,7 +107,7 @@ public class PowerUsageAdvanced extends PowerUsageBase { mMetricsFeatureProvider.action(getContext(), MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE, mShowAllApps); - restartBatteryStatsLoader(); + restartBatteryStatsLoader(BatteryUpdateType.MANUAL); return true; default: return super.onOptionsItemSelected(item); @@ -138,7 +139,7 @@ public class PowerUsageAdvanced extends PowerUsageBase { } @Override - protected void refreshUi() { + protected void refreshUi(@BatteryUpdateType int refreshType) { final Context context = getContext(); if (context == null) { return; diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java index b811f208b84..58d9d0885d3 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageBase.java +++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java @@ -15,6 +15,8 @@ */ package com.android.settings.fuelgauge; +import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.*; + import android.app.Activity; import android.app.LoaderManager; import android.content.Context; @@ -26,18 +28,17 @@ import android.view.Menu; import com.android.internal.os.BatteryStatsHelper; import com.android.settings.dashboard.DashboardFragment; -import com.android.settingslib.utils.AsyncLoader; /** * Common base class for things that need to show the battery usage graph. */ -public abstract class PowerUsageBase extends DashboardFragment - implements LoaderManager.LoaderCallbacks { +public abstract class PowerUsageBase extends DashboardFragment { // +1 to allow ordering for PowerUsageSummary. @VisibleForTesting static final int MENU_STATS_REFRESH = Menu.FIRST + 1; private static final String TAG = "PowerUsageBase"; + private static final String KEY_REFRESH_TYPE = "refresh_type"; protected BatteryStatsHelper mStatsHelper; protected UserManager mUm; @@ -57,8 +58,8 @@ public abstract class PowerUsageBase extends DashboardFragment setHasOptionsMenu(true); mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(getContext()); - mBatteryBroadcastReceiver.setBatteryChangedListener(() -> { - restartBatteryStatsLoader(); + mBatteryBroadcastReceiver.setBatteryChangedListener(type -> { + restartBatteryStatsLoader(type); }); } @@ -81,11 +82,14 @@ public abstract class PowerUsageBase extends DashboardFragment mBatteryBroadcastReceiver.unRegister(); } - protected void restartBatteryStatsLoader() { - getLoaderManager().restartLoader(0, Bundle.EMPTY, this); + protected void restartBatteryStatsLoader(int refreshType) { + final Bundle bundle = new Bundle(); + bundle.putInt(KEY_REFRESH_TYPE, refreshType); + + getLoaderManager().restartLoader(0, bundle, new PowerLoaderCallback()); } - protected abstract void refreshUi(); + protected abstract void refreshUi(@BatteryUpdateType int refreshType); protected void updatePreference(BatteryHistoryPreference historyPref) { final long startTime = System.currentTimeMillis(); @@ -93,21 +97,30 @@ public abstract class PowerUsageBase extends DashboardFragment BatteryUtils.logRuntime(TAG, "updatePreference", startTime); } - @Override - public Loader onCreateLoader(int id, - Bundle args) { - return new BatteryStatsHelperLoader(getContext()); - } + /** + * {@link android.app.LoaderManager.LoaderCallbacks} for {@link PowerUsageBase} to load + * the {@link BatteryStatsHelper} + */ + public class PowerLoaderCallback implements LoaderManager.LoaderCallbacks { + private int mRefreshType; - @Override - public void onLoadFinished(Loader loader, - BatteryStatsHelper statsHelper) { - mStatsHelper = statsHelper; - refreshUi(); - } + @Override + public Loader onCreateLoader(int id, + Bundle args) { + mRefreshType = args.getInt(KEY_REFRESH_TYPE); + return new BatteryStatsHelperLoader(getContext()); + } - @Override - public void onLoaderReset(Loader loader) { + @Override + public void onLoadFinished(Loader loader, + BatteryStatsHelper statsHelper) { + mStatsHelper = statsHelper; + refreshUi(mRefreshType); + } + @Override + public void onLoaderReset(Loader loader) { + + } } } diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 0563815dd71..e4f7a726c17 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -16,6 +16,8 @@ package com.android.settings.fuelgauge; +import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType; + import android.app.Activity; import android.app.LoaderManager; import android.app.LoaderManager.LoaderCallbacks; @@ -277,7 +279,7 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList } else { mStatsType = BatteryStats.STATS_SINCE_CHARGED; } - refreshUi(); + refreshUi(BatteryUpdateType.MANUAL); return true; case MENU_ADVANCED_BATTERY: new SubSettingLauncher(getContext()) @@ -291,14 +293,15 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList } } - protected void refreshUi() { + protected void refreshUi(@BatteryUpdateType int refreshType) { final Context context = getContext(); if (context == null) { return; } - // Only skip BatteryTipLoader for the first time when device is rotated - if (mNeedUpdateBatteryTip) { + // Skip BatteryTipLoader if device is rotated or only battery level change + if (mNeedUpdateBatteryTip + && refreshType != BatteryUpdateType.BATTERY_LEVEL) { restartBatteryTipLoader(); } else { mNeedUpdateBatteryTip = true; @@ -397,8 +400,9 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList } @Override - protected void restartBatteryStatsLoader() { - restartBatteryStatsLoader(true /* clearHeader */); + protected void restartBatteryStatsLoader(@BatteryUpdateType int refreshType) { + super.restartBatteryStatsLoader(refreshType); + mBatteryHeaderPreferenceController.quickUpdateHeaderPreference(); } @Override @@ -407,13 +411,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList mBatteryTipPreferenceController.saveInstanceState(outState); } - void restartBatteryStatsLoader(boolean clearHeader) { - super.restartBatteryStatsLoader(); - if (clearHeader) { - mBatteryHeaderPreferenceController.quickUpdateHeaderPreference(); - } - } - @Override public void onBatteryTipHandled(BatteryTip batteryTip) { restartBatteryTipLoader(); @@ -428,7 +425,7 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList mContext = context; mLoader = loader; mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(mContext); - mBatteryBroadcastReceiver.setBatteryChangedListener(() -> { + mBatteryBroadcastReceiver.setBatteryChangedListener(type -> { BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() { @Override public void onBatteryInfoLoaded(BatteryInfo info) { diff --git a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java index 178aa27c188..969cb11920e 100644 --- a/src/com/android/settings/network/PrivateDnsModeDialogPreference.java +++ b/src/com/android/settings/network/PrivateDnsModeDialogPreference.java @@ -156,16 +156,18 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreference imple @Override public void onClick(DialogInterface dialog, int which) { - final Context context = getContext(); - if (mMode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) { - // Only clickable if hostname is valid, so we could save it safely - Settings.Global.putString(context.getContentResolver(), HOSTNAME_KEY, - mEditText.getText().toString()); - } + if (which == DialogInterface.BUTTON_POSITIVE) { + final Context context = getContext(); + if (mMode.equals(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME)) { + // Only clickable if hostname is valid, so we could save it safely + Settings.Global.putString(context.getContentResolver(), HOSTNAME_KEY, + mEditText.getText().toString()); + } - FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context, - MetricsProto.MetricsEvent.ACTION_PRIVATE_DNS_MODE, mMode); - Settings.Global.putString(context.getContentResolver(), MODE_KEY, mMode); + FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context, + MetricsProto.MetricsEvent.ACTION_PRIVATE_DNS_MODE, mMode); + Settings.Global.putString(context.getContentResolver(), MODE_KEY, mMode); + } } @Override diff --git a/src/com/android/settings/notification/ZenModeRestrictNotificationsSettings.java b/src/com/android/settings/notification/ZenModeRestrictNotificationsSettings.java index 14b82f52836..8d0cd0eb5c8 100644 --- a/src/com/android/settings/notification/ZenModeRestrictNotificationsSettings.java +++ b/src/com/android/settings/notification/ZenModeRestrictNotificationsSettings.java @@ -16,22 +16,15 @@ package com.android.settings.notification; -import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ZEN_SHOW_CUSTOM; - import android.content.Context; import android.os.Bundle; import android.provider.SearchIndexableResource; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settings.R; -import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settingslib.core.AbstractPreferenceController; -import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.widget.FooterPreference; @@ -40,67 +33,21 @@ import java.util.List; public class ZenModeRestrictNotificationsSettings extends ZenModeSettingsBase implements Indexable { - protected static final int APP_MENU_SHOW_CUSTOM = 1; - protected boolean mShowMenuSelected; - @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - menu.add(0, APP_MENU_SHOW_CUSTOM, 0, R.string.zen_mode_restrict_notifications_enable_custom) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - } - - @Override - public boolean onOptionsItemSelected(MenuItem menuItem) { - if (menuItem.getItemId() == APP_MENU_SHOW_CUSTOM) { - final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext); - MetricsFeatureProvider metrics = featureFactory.getMetricsFeatureProvider(); - - mShowMenuSelected = !mShowMenuSelected; - - ZenModeVisEffectsCustomPreferenceController custom = - use(ZenModeVisEffectsCustomPreferenceController.class); - custom.setShownByMenu(mShowMenuSelected); - custom.displayPreference(getPreferenceScreen()); - - if (mShowMenuSelected) { - metrics.action(mContext, ACTION_ZEN_SHOW_CUSTOM, true); - } else { - metrics.action(mContext, ACTION_ZEN_SHOW_CUSTOM, false); - } - - return true; - } - return false; - } - - @Override - public void onPrepareOptionsMenu(Menu menu) { - if (mShowMenuSelected) { - menu.findItem(APP_MENU_SHOW_CUSTOM) - .setTitle(R.string.zen_mode_restrict_notifications_disable_custom); - } else { - menu.findItem(APP_MENU_SHOW_CUSTOM) - .setTitle(R.string.zen_mode_restrict_notifications_enable_custom); - } - - if (mShowMenuSelected && use(ZenModeVisEffectsCustomPreferenceController.class) - .areCustomOptionsSelected()) { - menu.findItem(APP_MENU_SHOW_CUSTOM).setEnabled(false); - } else { - menu.findItem(APP_MENU_SHOW_CUSTOM).setEnabled(true); - } - } - @Override protected List createPreferenceControllers(Context context) { return buildPreferenceControllers(context, getLifecycle()); } + @Override + public int getHelpResource() { + return R.string.help_uri_interruptions; + } + private static List buildPreferenceControllers(Context context, Lifecycle lifecycle) { List controllers = new ArrayList<>(); diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java index ec0f6192d94..62b3fe55dd6 100644 --- a/src/com/android/settings/notification/ZenModeSettings.java +++ b/src/com/android/settings/notification/ZenModeSettings.java @@ -30,6 +30,7 @@ import android.app.FragmentManager; import android.app.NotificationManager; import android.app.NotificationManager.Policy; import android.content.Context; +import android.icu.text.ListFormatter; import android.provider.SearchIndexableResource; import android.provider.Settings; import android.service.notification.ZenModeConfig; @@ -166,17 +167,20 @@ public class ZenModeSettings extends ZenModeSettingsBase { return mContext.getString(R.string.join_two_items, enabledCategories.get(0), enabledCategories.get(1).toLowerCase()); } else if (numCategories == 3){ - String secondaryText = mContext.getString(R.string.join_two_unrelated_items, - enabledCategories.get(0), enabledCategories.get(1).toLowerCase()); - return mContext.getString(R.string.join_many_items_last, secondaryText, - enabledCategories.get(2).toLowerCase()); + final List summaries = new ArrayList<>(); + summaries.add(enabledCategories.get(0)); + summaries.add(enabledCategories.get(1).toLowerCase()); + summaries.add(enabledCategories.get(2).toLowerCase()); + + return ListFormatter.getInstance().format(summaries); } else { - String secondaryText = mContext.getString(R.string.join_many_items_middle, - enabledCategories.get(0), enabledCategories.get(1).toLowerCase()); - secondaryText = mContext.getString(R.string.join_many_items_middle, secondaryText, - enabledCategories.get(2).toLowerCase()); - return mContext.getString(R.string.join_many_items_last, secondaryText, - mContext.getString(R.string.zen_mode_other_options)); + final List summaries = new ArrayList<>(); + summaries.add(enabledCategories.get(0)); + summaries.add(enabledCategories.get(1).toLowerCase()); + summaries.add(enabledCategories.get(2).toLowerCase()); + summaries.add(mContext.getString(R.string.zen_mode_other_options)); + + return ListFormatter.getInstance().format(summaries); } } diff --git a/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceController.java b/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceController.java index 83ab0377256..0a7f7269ca7 100644 --- a/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceController.java @@ -28,7 +28,6 @@ import com.android.settingslib.core.lifecycle.Lifecycle; public class ZenModeVisEffectsCustomPreferenceController extends AbstractZenModePreferenceController { - protected boolean mShowMenuSelected; protected static final int INTERRUPTIVE_EFFECTS = Policy.SUPPRESSED_EFFECT_AMBIENT | Policy.SUPPRESSED_EFFECT_PEEK | Policy.SUPPRESSED_EFFECT_LIGHTS @@ -41,11 +40,7 @@ public class ZenModeVisEffectsCustomPreferenceController @Override public boolean isAvailable() { - if (mShowMenuSelected) { - return true; - } - - return areCustomOptionsSelected(); + return true; } @Override @@ -64,10 +59,6 @@ public class ZenModeVisEffectsCustomPreferenceController }); } - protected void setShownByMenu(boolean shown) { - mShowMenuSelected = shown; - } - protected boolean areCustomOptionsSelected() { boolean allEffectsSuppressed = Policy.areAllVisualEffectsSuppressed(mBackend.mPolicy.suppressedVisualEffects); diff --git a/src/com/android/settings/search/DeviceIndexUpdateJobService.java b/src/com/android/settings/search/DeviceIndexUpdateJobService.java index 12a9cf00fcb..510da3a6226 100644 --- a/src/com/android/settings/search/DeviceIndexUpdateJobService.java +++ b/src/com/android/settings/search/DeviceIndexUpdateJobService.java @@ -53,10 +53,12 @@ public class DeviceIndexUpdateJobService extends JobService { @Override public boolean onStartJob(JobParameters params) { if (DEBUG) Log.d(TAG, "onStartJob"); - mRunningJob = true; - Thread thread = new Thread(() -> updateIndex(params)); - thread.setPriority(Thread.MIN_PRIORITY); - thread.start(); + if (!mRunningJob) { + mRunningJob = true; + Thread thread = new Thread(() -> updateIndex(params)); + thread.setPriority(Thread.MIN_PRIORITY); + thread.start(); + } return true; } diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java index af165daf124..8f07447cd80 100644 --- a/src/com/android/settings/slices/SettingsSliceProvider.java +++ b/src/com/android/settings/slices/SettingsSliceProvider.java @@ -18,6 +18,8 @@ package com.android.settings.slices; import static android.Manifest.permission.READ_SEARCH_INDEXABLES; +import static com.android.settings.wifi.calling.WifiCallingSliceHelper.PATH_WIFI_CALLING; + import android.app.PendingIntent; import android.app.slice.SliceManager; import android.content.ContentResolver; @@ -34,7 +36,13 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; +import androidx.slice.Slice; +import androidx.slice.SliceProvider; +import androidx.slice.builders.ListBuilder; +import androidx.slice.builders.SliceAction; + import com.android.settings.R; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.utils.ThreadUtils; import java.net.URISyntaxException; @@ -45,11 +53,6 @@ import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; -import androidx.slice.Slice; -import androidx.slice.SliceProvider; -import androidx.slice.builders.ListBuilder; -import androidx.slice.builders.SliceAction; - /** * A {@link SliceProvider} for Settings to enabled inline results in system apps. * @@ -160,6 +163,11 @@ public class SettingsSliceProvider extends SliceProvider { switch (path) { case "/" + PATH_WIFI: return createWifiSlice(sliceUri); + case "/" + PATH_WIFI_CALLING: + return FeatureFactory.getFactory(getContext()) + .getSlicesFeatureProvider() + .getNewWifiCallingSliceHelper(getContext()) + .createWifiCallingSlice(sliceUri); } SliceData cachedSliceData = mSliceWeakDataCache.get(sliceUri); diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java index 47a7f5a45bd..04097340ed3 100644 --- a/src/com/android/settings/slices/SliceBroadcastReceiver.java +++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java @@ -21,6 +21,7 @@ import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CH import static com.android.settings.slices.SettingsSliceProvider.ACTION_WIFI_CHANGED; import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY; import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_PLATFORM_DEFINED; +import static com.android.settings.wifi.calling.WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED; import android.app.slice.Slice; import android.content.BroadcastReceiver; @@ -79,6 +80,12 @@ public class SliceBroadcastReceiver extends BroadcastReceiver { context.getContentResolver().notifyChange(uri, null); }, 1000); break; + case ACTION_WIFI_CALLING_CHANGED: + FeatureFactory.getFactory(context) + .getSlicesFeatureProvider() + .getNewWifiCallingSliceHelper(context) + .handleWifiCallingChanged(intent); + break; } } diff --git a/src/com/android/settings/slices/SlicesFeatureProvider.java b/src/com/android/settings/slices/SlicesFeatureProvider.java index e5bba617e48..8dd6547b398 100644 --- a/src/com/android/settings/slices/SlicesFeatureProvider.java +++ b/src/com/android/settings/slices/SlicesFeatureProvider.java @@ -2,6 +2,8 @@ package com.android.settings.slices; import android.content.Context; +import com.android.settings.wifi.calling.WifiCallingSliceHelper; + /** * Manages Slices in Settings. */ @@ -24,4 +26,9 @@ public interface SlicesFeatureProvider { * If the data is already indexed, the data will not change. */ void indexSliceData(Context context); -} \ No newline at end of file + + /** + * Gets new WifiCallingSliceHelper object + */ + WifiCallingSliceHelper getNewWifiCallingSliceHelper(Context context); +} diff --git a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java index 8e5bc067150..16684bfb022 100644 --- a/src/com/android/settings/slices/SlicesFeatureProviderImpl.java +++ b/src/com/android/settings/slices/SlicesFeatureProviderImpl.java @@ -2,6 +2,7 @@ package com.android.settings.slices; import android.content.Context; +import com.android.settings.wifi.calling.WifiCallingSliceHelper; import com.android.settingslib.utils.ThreadUtils; /** @@ -39,4 +40,9 @@ public class SlicesFeatureProviderImpl implements SlicesFeatureProvider { SlicesIndexer indexer = getSliceIndexer(context); indexer.indexSliceData(); } -} \ No newline at end of file + + @Override + public WifiCallingSliceHelper getNewWifiCallingSliceHelper(Context context) { + return new WifiCallingSliceHelper(context); + } +} diff --git a/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java new file mode 100644 index 00000000000..7213148e97f --- /dev/null +++ b/src/com/android/settings/wifi/calling/WifiCallingSliceHelper.java @@ -0,0 +1,363 @@ +/* + * 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.wifi.calling; + +import static android.app.slice.Slice.EXTRA_TOGGLE_STATE; + +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.PersistableBundle; +import android.support.v4.graphics.drawable.IconCompat; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; + +import androidx.slice.Slice; +import androidx.slice.builders.ListBuilder; +import androidx.slice.builders.SliceAction; + +import com.android.ims.ImsManager; +import com.android.internal.annotations.VisibleForTesting; +import com.android.settings.R; +import com.android.settings.slices.SliceBroadcastReceiver; +import com.android.settings.slices.SliceBuilderUtils; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + +/** + * Helper class to control slices for wifi calling settings. + */ +public class WifiCallingSliceHelper { + + private static final String TAG = "WifiCallingSliceHelper"; + + /** + * Settings slice path to wifi calling setting. + */ + public static final String PATH_WIFI_CALLING = "wifi_calling"; + + /** + * Action passed for changes to wifi calling slice (toggle). + */ + public static final String ACTION_WIFI_CALLING_CHANGED = + "com.android.settings.wifi.calling.action.WIFI_CALLING_CHANGED"; + + /** + * Action for Wifi calling Settings activity which + * allows setting configuration for Wifi calling + * related settings + */ + public static final String ACTION_WIFI_CALLING_SETTINGS_ACTIVITY = + "android.settings.WIFI_CALLING_SETTINGS"; + + /** + * Timeout for querying wifi calling setting from ims manager. + */ + private static final int TIMEOUT_MILLIS = 2000; + + /** + * Time for which data contained in the slice can remain fresh. + */ + private static final int SLICE_TTL_MILLIS = 60000; + + protected SubscriptionManager mSubscriptionManager; + private final Context mContext; + + @VisibleForTesting + public WifiCallingSliceHelper(Context context) { + mContext = context; + } + + /** + * Returns Slice object for wifi calling settings. + * + * If wifi calling is being turned on and if wifi calling activation is needed for the current + * carrier, this method will return Slice with instructions to go to Settings App. + * + * If wifi calling is not supported for the current carrier, this method will return slice with + * not supported message. + * + * If wifi calling setting can be changed, this method will return the slice to toggle wifi + * calling option with ACTION_WIFI_CALLING_CHANGED as endItem. + */ + public Slice createWifiCallingSlice(Uri sliceUri) { + final int subId = getDefaultVoiceSubId(); + final String carrierName = getSimCarrierName(); + + if (subId <= SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + Log.d(TAG, "Invalid subscription Id"); + return getNonActionableWifiCallingSlice( + mContext.getString(R.string.wifi_calling_settings_title), + mContext.getString(R.string.wifi_calling_not_supported, carrierName), + sliceUri, SliceBuilderUtils.getSettingsIntent(mContext)); + } + + final ImsManager imsManager = getImsManager(subId); + + if (!imsManager.isWfcEnabledByPlatform() + || !imsManager.isWfcProvisionedOnDevice()) { + Log.d(TAG, "Wifi calling is either not provisioned or not enabled by Platform"); + return getNonActionableWifiCallingSlice( + mContext.getString(R.string.wifi_calling_settings_title), + mContext.getString(R.string.wifi_calling_not_supported, carrierName), + sliceUri, SliceBuilderUtils.getSettingsIntent(mContext)); + } + + try { + final boolean isWifiCallingEnabled = isWifiCallingEnabled(imsManager); + final Intent activationAppIntent = + getWifiCallingCarrierActivityIntent(subId); + + // Send this actionable wifi calling slice to toggle the setting + // only when there is no need for wifi calling activation with the server + if (activationAppIntent != null && !isWifiCallingEnabled) { + Log.d(TAG, "Needs Activation"); + // Activation needed for the next action of the user + // Give instructions to go to settings app + return getNonActionableWifiCallingSlice( + mContext.getString(R.string.wifi_calling_settings_title), + mContext.getString( + R.string.wifi_calling_settings_activation_instructions), + sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); + } + return getWifiCallingSlice(sliceUri, mContext, isWifiCallingEnabled); + } catch (InterruptedException | TimeoutException | ExecutionException e) { + Log.e(TAG, "Unable to read the current WiFi calling status", e); + return getNonActionableWifiCallingSlice( + mContext.getString(R.string.wifi_calling_settings_title), + mContext.getString(R.string.wifi_calling_turn_on), + sliceUri, getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); + } + } + + private boolean isWifiCallingEnabled(ImsManager imsManager) + throws InterruptedException, ExecutionException, TimeoutException { + final FutureTask isWifiOnTask = new FutureTask<>(new Callable() { + @Override + public Boolean call() { + return imsManager.isWfcEnabledByUser(); + } + }); + final ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.execute(isWifiOnTask); + + Boolean isWifiEnabledByUser = false; + isWifiEnabledByUser = isWifiOnTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); + + return isWifiEnabledByUser && imsManager.isNonTtyOrTtyOnVolteEnabled(); + } + + /** + * Builds a toggle slice where the intent takes you to the wifi calling page and the toggle + * enables/disables wifi calling. + */ + private Slice getWifiCallingSlice(Uri sliceUri, Context mContext, + boolean isWifiCallingEnabled) { + + final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); + final String title = mContext.getString(R.string.wifi_calling_settings_title); + return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS) + .setColor(R.color.material_blue_500) + .addRow(b -> b + .setTitle(title) + .addEndItem( + new SliceAction( + getBroadcastIntent(ACTION_WIFI_CALLING_CHANGED), + null /* actionTitle */, isWifiCallingEnabled)) + .setPrimaryAction(new SliceAction( + getActivityIntent(ACTION_WIFI_CALLING_SETTINGS_ACTIVITY), + icon, + title))) + .build(); + } + + protected ImsManager getImsManager(int subId) { + return ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(subId)); + } + + private Integer getWfcMode(ImsManager imsManager) + throws InterruptedException, ExecutionException, TimeoutException { + FutureTask wfcModeTask = new FutureTask<>(new Callable() { + @Override + public Integer call() { + return imsManager.getWfcMode(false); + } + }); + ExecutorService executor = Executors.newSingleThreadExecutor(); + executor.execute(wfcModeTask); + return wfcModeTask.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); + } + + /** + * Handles wifi calling setting change from wifi calling slice and posts notification. Should be + * called when intent action is ACTION_WIFI_CALLING_CHANGED. Executed in @WorkerThread + * + * @param intent action performed + */ + public void handleWifiCallingChanged(Intent intent) { + final int subId = getDefaultVoiceSubId(); + + if (subId > SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + final ImsManager imsManager = getImsManager(subId); + if (imsManager.isWfcEnabledByPlatform() + || imsManager.isWfcProvisionedOnDevice()) { + final boolean currentValue = imsManager.isWfcEnabledByUser() + && imsManager.isNonTtyOrTtyOnVolteEnabled(); + final boolean newValue = intent.getBooleanExtra(EXTRA_TOGGLE_STATE, + currentValue); + final Intent activationAppIntent = + getWifiCallingCarrierActivityIntent(subId); + if (!newValue || activationAppIntent == null) { + // If either the action is to turn off wifi calling setting + // or there is no activation involved - Update the setting + if (newValue != currentValue) { + imsManager.setWfcSetting(newValue); + } + } + } + } + // notify change in slice in any case to get re-queried. This would result in displaying + // appropriate message with the updated setting. + final Uri uri = SliceBuilderUtils.getUri(PATH_WIFI_CALLING, false /*isPlatformSlice*/); + mContext.getContentResolver().notifyChange(uri, null); + } + + /** + * Returns Slice with the title and subtitle provided as arguments with wifi signal Icon. + * + * @param title Title of the slice + * @param subtitle Subtitle of the slice + * @param sliceUri slice uri + * @return Slice with title and subtitle + */ + // TODO(b/79548264) asses different scenarios and return null instead of non-actionable slice + private Slice getNonActionableWifiCallingSlice(String title, String subtitle, Uri sliceUri, + PendingIntent primaryActionIntent) { + final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.wifi_signal); + return new ListBuilder(mContext, sliceUri, SLICE_TTL_MILLIS) + .setColor(R.color.material_blue_500) + .addRow(b -> b + .setTitle(title) + .setSubtitle(subtitle) + .setPrimaryAction(new SliceAction( + primaryActionIntent, icon, + title))) + .build(); + } + + /** + * Returns {@code true} when the key is enabled for the carrier, and {@code false} otherwise. + */ + private boolean isCarrierConfigManagerKeyEnabled(Context mContext, String key, + int subId, boolean defaultValue) { + final CarrierConfigManager configManager = getCarrierConfigManager(mContext); + boolean ret = false; + if (configManager != null) { + final PersistableBundle bundle = configManager.getConfigForSubId(subId); + if (bundle != null) { + ret = bundle.getBoolean(key, defaultValue); + } + } + return ret; + } + + protected CarrierConfigManager getCarrierConfigManager(Context mContext) { + return mContext.getSystemService(CarrierConfigManager.class); + } + + /** + * Returns the current default voice subId obtained from SubscriptionManager + */ + protected int getDefaultVoiceSubId() { + if (mSubscriptionManager == null) { + mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); + } + return SubscriptionManager.getDefaultVoiceSubscriptionId(); + } + + /** + * Returns Intent of the activation app required to activate wifi calling or null if there is no + * need for activation. + */ + protected Intent getWifiCallingCarrierActivityIntent(int subId) { + final CarrierConfigManager configManager = getCarrierConfigManager(mContext); + if (configManager == null) { + return null; + } + + final PersistableBundle bundle = configManager.getConfigForSubId(subId); + if (bundle == null) { + return null; + } + + final String carrierApp = bundle.getString( + CarrierConfigManager.KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING); + if (TextUtils.isEmpty(carrierApp)) { + return null; + } + + final ComponentName componentName = ComponentName.unflattenFromString(carrierApp); + if (componentName == null) { + return null; + } + + final Intent intent = new Intent(); + intent.setComponent(componentName); + return intent; + } + + private PendingIntent getBroadcastIntent(String action) { + final Intent intent = new Intent(action); + intent.setClass(mContext, SliceBroadcastReceiver.class); + return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent, + PendingIntent.FLAG_CANCEL_CURRENT); + } + + /** + * Returns PendingIntent to start activity specified by action + */ + private PendingIntent getActivityIntent(String action) { + final Intent intent = new Intent(action); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */); + } + + /** + * Returns carrier id name of the current Subscription + */ + private String getSimCarrierName() { + final TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class); + final CharSequence carrierName = telephonyManager.getSimCarrierIdName(); + if (carrierName == null) { + return mContext.getString(R.string.carrier); + } + return carrierName.toString(); + } + +} diff --git a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java index ed9501554eb..ced8fc4a2e4 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdaterTest.java @@ -73,6 +73,7 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { private AvailableMediaBluetoothDeviceUpdater mBluetoothDeviceUpdater; private Collection cachedDevices; private ShadowAudioManager mShadowAudioManager; + private BluetoothDevicePreference mPreference; @Before public void setUp() { @@ -93,6 +94,7 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { mBluetoothDeviceUpdater = spy(new AvailableMediaBluetoothDeviceUpdater(mDashboardFragment, mDevicePreferenceCallback, mLocalManager)); mBluetoothDeviceUpdater.setPrefContext(mContext); + mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, false); doNothing().when(mBluetoothDeviceUpdater).addPreference(any()); doNothing().when(mBluetoothDeviceUpdater).removePreference(any()); } @@ -208,5 +210,12 @@ public class AvailableMediaBluetoothDeviceUpdaterTest { verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice); } + + @Test + public void onClick_Preference_setActive() { + mBluetoothDeviceUpdater.onPreferenceClick(mPreference); + + verify(mCachedBluetoothDevice).setActive(); + } } diff --git a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java index fae014f7b10..547727beced 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdaterTest.java @@ -57,7 +57,8 @@ public class SavedBluetoothDeviceUpdaterTest { private LocalBluetoothProfileManager mLocalBluetoothProfileManager; private Context mContext; - private BluetoothDeviceUpdater mBluetoothDeviceUpdater; + private SavedBluetoothDeviceUpdater mBluetoothDeviceUpdater; + private BluetoothDevicePreference mPreference; @Before public void setUp() { @@ -71,6 +72,7 @@ public class SavedBluetoothDeviceUpdaterTest { mBluetoothDeviceUpdater = spy(new SavedBluetoothDeviceUpdater(mDashboardFragment, mDevicePreferenceCallback, mLocalManager)); mBluetoothDeviceUpdater.setPrefContext(mContext); + mPreference = new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, false); doNothing().when(mBluetoothDeviceUpdater).addPreference(any()); doNothing().when(mBluetoothDeviceUpdater).removePreference(any()); } @@ -110,4 +112,11 @@ public class SavedBluetoothDeviceUpdaterTest { verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice); } + + @Test + public void onClick_Preference_setConnect() { + mBluetoothDeviceUpdater.onPreferenceClick(mPreference); + + verify(mCachedBluetoothDevice).connect(true); + } } diff --git a/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java deleted file mode 100644 index bdaad0a426c..00000000000 --- a/tests/robotests/src/com/android/settings/development/BluetoothDelayReportsPreferenceControllerTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.development; - -import static com.android.settings.development.BluetoothDelayReportsPreferenceController - .BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.os.SystemProperties; -import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.PreferenceScreen; - -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 BluetoothDelayReportsPreferenceControllerTest { - - @Mock - private PreferenceScreen mPreferenceScreen; - - private Context mContext; - private SwitchPreference mPreference; - private BluetoothDelayReportsPreferenceController mController; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - mPreference = new SwitchPreference(mContext); - mController = spy(new BluetoothDelayReportsPreferenceController(mContext)); - when(mPreferenceScreen.findPreference(mController.getPreferenceKey())) - .thenReturn(mPreference); - mController.displayPreference(mPreferenceScreen); - } - - @Test - public void onPreferenceChanged_settingDisabled_turnOnDelayReports() { - mController.onPreferenceChange(mPreference, true /* new value */); - - final boolean mode = SystemProperties.getBoolean( - BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */); - - assertThat(mode).isTrue(); - } - - @Test - public void onPreferenceChanged_settingDisabled_turnOffDelayReports() { - mController.onPreferenceChange(mPreference, false /* new value */); - - final boolean mode = SystemProperties.getBoolean( - BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */); - - assertThat(mode).isFalse(); - } - - @Test - public void updateState_settingDisabled_preferenceShouldBeChecked() { - SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, - Boolean.toString(true)); - mController.updateState(mPreference); - - assertThat(mPreference.isChecked()).isTrue(); - } - - @Test - public void updateState_settingDisabled_preferenceShouldNotBeChecked() { - SystemProperties.set(BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, - Boolean.toString(false)); - mController.updateState(mPreference); - - assertThat(mPreference.isChecked()).isFalse(); - } - - @Test - public void onDeveloperOptionsDisabled_shouldDisablePreference() { - mController.onDeveloperOptionsDisabled(); - - final boolean mode = SystemProperties.getBoolean( - BLUETOOTH_DISABLE_AVDTP_DELAY_REPORTS_PROPERTY, false /* default */); - - assertThat(mode).isFalse(); - assertThat(mPreference.isEnabled()).isFalse(); - assertThat(mPreference.isChecked()).isFalse(); - } -} diff --git a/tests/robotests/src/com/android/settings/development/BluetoothInbandRingingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothInbandRingingPreferenceControllerTest.java deleted file mode 100644 index f91bd44bbfa..00000000000 --- a/tests/robotests/src/com/android/settings/development/BluetoothInbandRingingPreferenceControllerTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.development; - -import static com.android.settings.development.BluetoothInbandRingingPreferenceController.BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY; -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 static org.mockito.Mockito.when; - -import android.content.Context; -import android.os.SystemProperties; -import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.PreferenceScreen; - -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 BluetoothInbandRingingPreferenceControllerTest { - - @Mock - private SwitchPreference mPreference; - @Mock - private PreferenceScreen mPreferenceScreen; - - private Context mContext; - private BluetoothInbandRingingPreferenceController mController; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - mController = spy(new BluetoothInbandRingingPreferenceController(mContext)); - doReturn(true).when(mController).isInbandRingingSupported(); - when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn( - mPreference); - mController.displayPreference(mPreferenceScreen); - } - - @Test - public void isAvailable_inbandRingingNotSupported_shouldReturnFalse() { - doReturn(false).when(mController).isInbandRingingSupported(); - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void isAvailable_inbandRingingSupported_shouldReturnTrue() { - assertThat(mController.isAvailable()).isTrue(); - } - - @Test - public void onPreferenceChanged_settingEnabled_turnOnBluetoothSnoopLog() { - mController.onPreferenceChange(mPreference, true /* new value */); - - final boolean mode = SystemProperties - .getBoolean(BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY, false /* default */); - - assertThat(mode).isTrue(); - } - - @Test - public void onPreferenceChanged_settingDisabled_turnOffBluetoothSnoopLog() { - mController.onPreferenceChange(mPreference, false /* new value */); - - final boolean mode = SystemProperties - .getBoolean(BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY, false /* default */); - - assertThat(mode).isFalse(); - } - - @Test - public void updateState_settingEnabled_preferenceShouldBeChecked() { - SystemProperties.set(BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY, Boolean.toString(true)); - mController.updateState(mPreference); - - verify(mPreference).setChecked(true); - } - - @Test - public void updateState_settingDisabled_preferenceShouldNotBeChecked() { - SystemProperties.set(BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY, Boolean.toString(false)); - mController.updateState(mPreference); - - verify(mPreference).setChecked(false); - } - - @Test - public void onDeveloperOptionsDisabled_shouldDisablePreference() { - mController.onDeveloperOptionsDisabled(); - - final boolean mode = SystemProperties - .getBoolean(BLUETOOTH_DISABLE_INBAND_RINGING_PROPERTY, false /* default */); - - assertThat(mode).isFalse(); - verify(mPreference).setEnabled(false); - verify(mPreference).setChecked(false); - } -} diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java index 9272b46b283..da32ce81909 100644 --- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java @@ -131,7 +131,6 @@ public class DevelopmentSettingsDashboardFragmentTest { @Config(shadows = { ShadowPictureColorModePreferenceController.class, ShadowAdbPreferenceController.class, - ShadowBluetoothInbandRingingPreferenceController.class, ShadowClearAdbKeysPreferenceController.class }) public void searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable() { @@ -282,15 +281,6 @@ public class DevelopmentSettingsDashboardFragmentTest { } } - @Implements(BluetoothInbandRingingPreferenceController.class) - public static class ShadowBluetoothInbandRingingPreferenceController { - - @Implementation - public boolean isAvailable() { - return true; - } - } - @Implements(ClearAdbKeysPreferenceController.class) public static class ShadowClearAdbKeysPreferenceController { diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBroadcastReceiverTest.java index 3fdbe837425..4583dd1b3b4 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBroadcastReceiverTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBroadcastReceiverTest.java @@ -15,8 +15,11 @@ */ package com.android.settings.fuelgauge; +import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -70,14 +73,14 @@ public class BatteryBroadcastReceiverTest { } @Test - public void testOnReceive_batteryDataChanged_dataUpdated() { + public void testOnReceive_batteryLevelChanged_dataUpdated() { mBatteryBroadcastReceiver.onReceive(mContext, mChargingIntent); assertThat(mBatteryBroadcastReceiver.mBatteryLevel) .isEqualTo(Utils.getBatteryPercentage(mChargingIntent)); assertThat(mBatteryBroadcastReceiver.mBatteryStatus) .isEqualTo(Utils.getBatteryStatus(mContext.getResources(), mChargingIntent)); - verify(mBatteryListener).onBatteryChanged(); + verify(mBatteryListener).onBatteryChanged(BatteryUpdateType.BATTERY_LEVEL); } @Test @@ -85,7 +88,7 @@ public class BatteryBroadcastReceiverTest { mBatteryBroadcastReceiver.onReceive(mContext, new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)); - verify(mBatteryListener).onBatteryChanged(); + verify(mBatteryListener).onBatteryChanged(BatteryUpdateType.BATTERY_SAVER); } @Test @@ -100,7 +103,7 @@ public class BatteryBroadcastReceiverTest { assertThat(mBatteryBroadcastReceiver.mBatteryLevel).isEqualTo(batteryLevel); assertThat(mBatteryBroadcastReceiver.mBatteryStatus).isEqualTo(batteryStatus); - verify(mBatteryListener, never()).onBatteryChanged(); + verify(mBatteryListener, never()).onBatteryChanged(anyInt()); } @Test @@ -115,6 +118,6 @@ public class BatteryBroadcastReceiverTest { assertThat(mBatteryBroadcastReceiver.mBatteryStatus) .isEqualTo(Utils.getBatteryStatus(mContext.getResources(), mChargingIntent)); // 2 times because register will force update the battery - verify(mBatteryListener, times(2)).onBatteryChanged(); + verify(mBatteryListener, times(2)).onBatteryChanged(BatteryUpdateType.MANUAL); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java index 4a905b4603a..9b61e5fe131 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java @@ -18,6 +18,7 @@ package com.android.settings.fuelgauge; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -86,7 +87,7 @@ public class PowerUsageAdvancedTest { @Test public void testOptionsMenu_menuAppToggle_metricEventInvoked() { mFragment.mShowAllApps = false; - doNothing().when(mFragment).restartBatteryStatsLoader(); + doNothing().when(mFragment).restartBatteryStatsLoader(anyInt()); mFragment.onOptionsItemSelected(mToggleAppsMenu); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageBaseTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageBaseTest.java index d9f572deefa..eb683c072e0 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageBaseTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageBaseTest.java @@ -74,7 +74,7 @@ public class PowerUsageBaseTest { } @Override - protected void refreshUi() { + protected void refreshUi(int refreshType) { // Do nothing } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java index b48f00e295b..07341a14656 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java @@ -149,7 +149,7 @@ public class PowerUsageSummaryTest { mFragment.initFeatureProvider(); mBatteryMeterView = new BatteryMeterView(mRealContext); mBatteryMeterView.mDrawable = new BatteryMeterView.BatteryMeterDrawable(mRealContext, 0); - doNothing().when(mFragment).restartBatteryStatsLoader(); + doNothing().when(mFragment).restartBatteryStatsLoader(anyInt()); doReturn(mock(LoaderManager.class)).when(mFragment).getLoaderManager(); doReturn(MENU_ADVANCED_BATTERY).when(mAdvancedPageMenu).getItemId(); @@ -316,15 +316,6 @@ public class PowerUsageSummaryTest { verify(mSummary1, times(2)).setOnLongClickListener(any(View.OnLongClickListener.class)); } - @Test - public void restartBatteryStatsLoader_notClearHeader_quickUpdateNotInvoked() { - mFragment.mBatteryHeaderPreferenceController = mBatteryHeaderPreferenceController; - - mFragment.restartBatteryStatsLoader(false /* clearHeader */); - - verify(mBatteryHeaderPreferenceController, never()).quickUpdateHeaderPreference(); - } - @Test public void optionsMenu_advancedPageEnabled() { when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled()) @@ -360,7 +351,18 @@ public class PowerUsageSummaryTest { when(mFragment.mBatteryTipPreferenceController.needUpdate()).thenReturn(false); mFragment.updateBatteryTipFlag(new Bundle()); - mFragment.refreshUi(); + mFragment.refreshUi(BatteryBroadcastReceiver.BatteryUpdateType.MANUAL); + + verify(mFragment, never()).restartBatteryTipLoader(); + } + + @Test + public void refreshUi_batteryLevelChanged_doNotUpdateBatteryTip() { + mFragment.mBatteryTipPreferenceController = mock(BatteryTipPreferenceController.class); + when(mFragment.mBatteryTipPreferenceController.needUpdate()).thenReturn(true); + mFragment.updateBatteryTipFlag(new Bundle()); + + mFragment.refreshUi(BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_LEVEL); verify(mFragment, never()).restartBatteryTipLoader(); } @@ -371,7 +373,7 @@ public class PowerUsageSummaryTest { when(mFragment.mBatteryTipPreferenceController.needUpdate()).thenReturn(true); mFragment.updateBatteryTipFlag(new Bundle()); - mFragment.refreshUi(); + mFragment.refreshUi(BatteryBroadcastReceiver.BatteryUpdateType.MANUAL); verify(mFragment).restartBatteryTipLoader(); } diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogPreferenceTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogPreferenceTest.java index e9ffa8ac4c6..dfea6fba515 100644 --- a/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/network/PrivateDnsModeDialogPreferenceTest.java @@ -28,7 +28,10 @@ import static org.mockito.Mockito.when; import android.app.AlertDialog; import android.app.Fragment; +import android.content.ContentResolver; import android.content.Context; +import android.content.DialogInterface; +import android.net.ConnectivityManager; import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; @@ -150,4 +153,36 @@ public class PrivateDnsModeDialogPreferenceTest { assertThat(mSaveButton.isEnabled()).named("provider: " + invalid).isFalse(); } } + + @Test + public void testOnClick_positiveButtonClicked_saveData() { + // Set the default settings to OFF + final ContentResolver contentResolver = mContext.getContentResolver(); + Settings.Global.putString(contentResolver, Settings.Global.PRIVATE_DNS_MODE, + ConnectivityManager.PRIVATE_DNS_MODE_OFF); + + mPreference.mMode = ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; + mPreference.onClick(null, DialogInterface.BUTTON_POSITIVE); + + // Change to OPPORTUNISTIC + assertThat(Settings.Global.getString(contentResolver, + Settings.Global.PRIVATE_DNS_MODE)).isEqualTo( + ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC); + } + + @Test + public void testOnClick_negativeButtonClicked_doNothing() { + // Set the default settings to OFF + final ContentResolver contentResolver = mContext.getContentResolver(); + Settings.Global.putString(contentResolver, Settings.Global.PRIVATE_DNS_MODE, + ConnectivityManager.PRIVATE_DNS_MODE_OFF); + + mPreference.mMode = ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; + mPreference.onClick(null, DialogInterface.BUTTON_NEGATIVE); + + // Still equal to OFF + assertThat(Settings.Global.getString(contentResolver, + Settings.Global.PRIVATE_DNS_MODE)).isEqualTo( + ConnectivityManager.PRIVATE_DNS_MODE_OFF); + } } diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java index 5b2782fb6b7..39e9271fa2f 100644 --- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java +++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsTest.java @@ -134,13 +134,13 @@ public class ZenModeSettingsTest { public void testGetCallsSettingSummary_contacts() { Policy policy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | Policy.PRIORITY_CATEGORY_CALLS, Policy.PRIORITY_SENDERS_CONTACTS, 0, 0); - assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("From contacts only"); + assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("From contacts"); } @Test public void testGetCallsSettingSummary_repeatCallers() { Policy policy = new Policy(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0); - assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("From repeat callers only"); + assertThat(mBuilder.getCallsSettingSummary(policy)).isEqualTo("From repeat callers"); } @Test diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceControllerTest.java index 14de98cdf27..b1692bc7629 100644 --- a/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectsCustomPreferenceControllerTest.java @@ -88,23 +88,14 @@ public class ZenModeVisEffectsCustomPreferenceControllerTest { } @Test - public void isAvailable_menuOff_noVisEffects() { + public void isAvailable_noVisEffects() { mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 0); - mController.mShowMenuSelected = false; - assertThat(mController.isAvailable()).isFalse(); - } - - @Test - public void isAvailable_menuOn_noVisEffects() { - mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 0); - mController.mShowMenuSelected = true; assertThat(mController.isAvailable()).isTrue(); } @Test - public void isAvailable_menuOn_visEffects() { + public void isAvailable_visEffects() { mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 1); - mController.mShowMenuSelected = false; assertThat(mController.isAvailable()).isTrue(); } diff --git a/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java new file mode 100644 index 00000000000..ac3ff3ff635 --- /dev/null +++ b/tests/robotests/src/com/android/settings/wifi/calling/WifiCallingSliceHelperTest.java @@ -0,0 +1,316 @@ +/* + * 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.wifi.calling; + +import static android.app.slice.Slice.EXTRA_TOGGLE_STATE; +import static android.app.slice.Slice.HINT_TITLE; +import static android.app.slice.SliceItem.FORMAT_TEXT; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.net.Uri; +import android.telephony.CarrierConfigManager; + +import androidx.slice.Slice; +import androidx.slice.SliceItem; +import androidx.slice.SliceMetadata; +import androidx.slice.SliceProvider; +import androidx.slice.core.SliceAction; +import androidx.slice.core.SliceQuery; +import androidx.slice.widget.SliceLiveData; + +import com.android.ims.ImsManager; +import com.android.settings.R; +import com.android.settings.slices.SettingsSliceProvider; +import com.android.settings.slices.SliceBroadcastReceiver; +import com.android.settings.slices.SliceBuilderUtils; +import com.android.settings.slices.SliceData; +import com.android.settings.slices.SlicesFeatureProvider; +import com.android.settings.testutils.FakeFeatureFactory; +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; + +import java.util.List; + +@RunWith(SettingsRobolectricTestRunner.class) +public class WifiCallingSliceHelperTest { + + private Context mContext; + @Mock + private CarrierConfigManager mMockCarrierConfigManager; + + @Mock + private ImsManager mMockImsManager; + + private final Uri mWfcURI = Uri.parse("content://com.android.settings.slices/wifi_calling"); + + private FakeWifiCallingSliceHelper mWfcSliceHelper; + private SettingsSliceProvider mProvider; + private SliceBroadcastReceiver mReceiver; + private FakeFeatureFactory mFeatureFactory; + private SlicesFeatureProvider mSlicesFeatureProvider; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + + //setup for SettingsSliceProvider tests + mProvider = spy(new SettingsSliceProvider()); + doReturn(mContext).when(mProvider).getContext(); + + //setup for SliceBroadcastReceiver test + mReceiver = spy(new SliceBroadcastReceiver()); + + mFeatureFactory = FakeFeatureFactory.setupForTest(); + mSlicesFeatureProvider = mFeatureFactory.getSlicesFeatureProvider(); + + // Prevent crash in SliceMetadata. + Resources resources = spy(mContext.getResources()); + doReturn(60).when(resources).getDimensionPixelSize(anyInt()); + doReturn(resources).when(mContext).getResources(); + + mWfcSliceHelper = new FakeWifiCallingSliceHelper(mContext); + + // Set-up specs for SliceMetadata. + SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); + } + + @Test + public void test_CreateWifiCallingSlice_invalidSubId() { + mWfcSliceHelper.setDefaultVoiceSubId(-1); + + final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI); + + testWifiCallingSettingsUnavailableSlice(slice, null, + SliceBuilderUtils.getSettingsIntent(mContext)); + } + + @Test + public void test_CreateWifiCallingSlice_wfcNotSupported() { + doReturn(false).when(mMockImsManager).isWfcEnabledByPlatform(); + + final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI); + + assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testWifiCallingSettingsUnavailableSlice(slice, null, + SliceBuilderUtils.getSettingsIntent(mContext)); + } + + @Test + public void test_CreateWifiCallingSlice_needsActivation() { + /* In cases where activation is needed and the user action + would be turning on the wifi calling (i.e. if wifi calling is + turned off) we need to guide the user to wifi calling settings + activity so the user can perform the activation there.(PrimaryAction) + */ + doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform(); + doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice(); + doReturn(false).when(mMockImsManager).isWfcEnabledByUser(); + doReturn(false).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled(); + doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1); + mWfcSliceHelper.setActivationAppIntent(new Intent()); // dummy Intent + + final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI); + + assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testWifiCallingSettingsUnavailableSlice(slice, null, + getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY)); + } + + @Test + public void test_CreateWifiCallingSlice_success() { + doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform(); + doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice(); + doReturn(true).when(mMockImsManager).isWfcEnabledByUser(); + doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled(); + doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1); + + final Slice slice = mWfcSliceHelper.createWifiCallingSlice(mWfcURI); + + assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testWifiCallingSettingsToggleSlice(slice, null); + } + + @Test + public void test_SettingSliceProvider_getsRightSliceWifiCalling() { + doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform(); + doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice(); + doReturn(true).when(mMockImsManager).isWfcEnabledByUser(); + doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled(); + doReturn(null).when(mMockCarrierConfigManager).getConfigForSubId(1); + doReturn(mWfcSliceHelper).when(mSlicesFeatureProvider) + .getNewWifiCallingSliceHelper(mContext); + + final Slice slice = mProvider.onBindSlice(mWfcURI); + + assertThat(mWfcSliceHelper.getDefaultVoiceSubId()).isEqualTo(1); + testWifiCallingSettingsToggleSlice(slice, null); + } + + @Test + public void test_SliceBroadcastReceiver_toggleOffWifiCalling() { + doReturn(true).when(mMockImsManager).isWfcEnabledByPlatform(); + doReturn(true).when(mMockImsManager).isWfcProvisionedOnDevice(); + doReturn(false).when(mMockImsManager).isWfcEnabledByUser(); + doReturn(true).when(mMockImsManager).isNonTtyOrTtyOnVolteEnabled(); + doReturn(mWfcSliceHelper).when(mSlicesFeatureProvider) + .getNewWifiCallingSliceHelper(mContext); + mWfcSliceHelper.setActivationAppIntent(null); + + ArgumentCaptor mWfcSettingCaptor = ArgumentCaptor.forClass(Boolean.class); + + // turn on Wifi calling setting + Intent intent = new Intent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED); + intent.putExtra(EXTRA_TOGGLE_STATE, true); + + // change the setting + mReceiver.onReceive(mContext, intent); + + verify((mMockImsManager)).setWfcSetting(mWfcSettingCaptor.capture()); + + // assert the change + assertThat(mWfcSettingCaptor.getValue()).isTrue(); + } + + private void testWifiCallingSettingsUnavailableSlice(Slice slice, + SliceData sliceData, PendingIntent expectedPrimaryAction) { + final SliceMetadata metadata = SliceMetadata.from(mContext, slice); + + //Check there is no toggle action + final List toggles = metadata.getToggles(); + assertThat(toggles).isEmpty(); + + // Check whether the primary action is to open wifi calling settings activity + final PendingIntent primaryPendingIntent = + metadata.getPrimaryAction().getAction(); + assertThat(primaryPendingIntent).isEqualTo(expectedPrimaryAction); + + // Check the title + final List sliceItems = slice.getItems(); + assertTitle(sliceItems, mContext.getString(R.string.wifi_calling_settings_title)); + } + + private void testWifiCallingSettingsToggleSlice(Slice slice, + SliceData sliceData) { + final SliceMetadata metadata = SliceMetadata.from(mContext, slice); + + final List toggles = metadata.getToggles(); + assertThat(toggles).hasSize(1); + + final SliceAction mainToggleAction = toggles.get(0); + + // Check intent in Toggle Action + final PendingIntent togglePendingIntent = mainToggleAction.getAction(); + final PendingIntent expectedToggleIntent = getBroadcastIntent( + WifiCallingSliceHelper.ACTION_WIFI_CALLING_CHANGED); + assertThat(togglePendingIntent).isEqualTo(expectedToggleIntent); + + // Check primary intent + final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction(); + final PendingIntent expectedPendingIntent = + getActivityIntent(WifiCallingSliceHelper.ACTION_WIFI_CALLING_SETTINGS_ACTIVITY); + assertThat(primaryPendingIntent).isEqualTo(expectedPendingIntent); + + // Check the title + final List sliceItems = slice.getItems(); + assertTitle(sliceItems, mContext.getString(R.string.wifi_calling_settings_title)); + } + + private PendingIntent getBroadcastIntent(String action) { + final Intent intent = new Intent(action); + intent.setClass(mContext, SliceBroadcastReceiver.class); + return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent, + PendingIntent.FLAG_CANCEL_CURRENT); + } + + private PendingIntent getActivityIntent(String action) { + final Intent intent = new Intent(action); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */); + } + + private void assertTitle(List sliceItems, String title) { + boolean hasTitle = false; + for (SliceItem item : sliceItems) { + List titleItems = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE, + null /* non-hints */); + if (titleItems == null) { + continue; + } + + hasTitle = true; + for (SliceItem subTitleItem : titleItems) { + assertThat(subTitleItem.getText()).isEqualTo(title); + } + } + assertThat(hasTitle).isTrue(); + } + private class FakeWifiCallingSliceHelper extends WifiCallingSliceHelper { + int mSubId = 1; + + private Intent mActivationAppIntent; + FakeWifiCallingSliceHelper(Context context) { + super(context); + mActivationAppIntent = null; + } + + @Override + protected CarrierConfigManager getCarrierConfigManager(Context mContext) { + return mMockCarrierConfigManager; + } + + @Override + protected ImsManager getImsManager(int subId) { + return mMockImsManager; + } + + protected int getDefaultVoiceSubId() { + return mSubId; + } + + protected void setDefaultVoiceSubId(int id) { + mSubId = id; + } + + @Override + protected Intent getWifiCallingCarrierActivityIntent(int subId) { + return mActivationAppIntent; + } + + public void setActivationAppIntent(Intent intent) { + mActivationAppIntent = intent; + } + } +}