Merge "Move launch button from 3-buttons panel to the top right corner" into main
diff --git a/aconfig/OWNERS b/aconfig/OWNERS
index 1131545..c26a190 100644
--- a/aconfig/OWNERS
+++ b/aconfig/OWNERS
@@ -1 +1,3 @@
per-file settings_accessibility_flag_declarations.aconfig = file:/src/com/android/settings/accessibility/OWNERS
+per-file settings_biometrics_integration_declarations.aconfig = file:platform/vendor/unbundled_google/packages/SettingsGoogle:/future/biometrics/OWNERS
+
diff --git a/res/layout/audio_sharing_device_item.xml b/res/layout/audio_sharing_device_item.xml
new file mode 100644
index 0000000..f8e7454
--- /dev/null
+++ b/res/layout/audio_sharing_device_item.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:id="@+id/device_button"
+ android:overScrollMode="never"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="center"
+ android:text=""/>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/dialog_audio_sharing.xml b/res/layout/dialog_audio_sharing.xml
new file mode 100644
index 0000000..9624c90
--- /dev/null
+++ b/res/layout/dialog_audio_sharing.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="24dp"
+ android:orientation="vertical">
+
+ <TextView
+ style="@style/device_info_dialog_value"
+ android:id="@+id/share_audio_subtitle1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="center"
+ android:layout_gravity="center"/>
+
+ <TextView
+ style="@style/device_info_dialog_value"
+ android:id="@+id/share_audio_subtitle2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="center"
+ android:layout_gravity="center"/>
+
+ <com.android.internal.widget.RecyclerView
+ android:visibility="visible"
+ android:id="@+id/btn_list"
+ android:nestedScrollingEnabled="false"
+ android:overScrollMode="never"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ba56c53..9d8fc1c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3169,6 +3169,8 @@
<string name="apn_settings">APNs</string>
<!-- Screen title after user selects APNs setting option -->
<string name="apn_edit">Edit access point</string>
+ <!-- Screen title after user selects add APNs setting -->
+ <string name="apn_add">Add access point</string>
<!-- Edit access point label summary text when no value has been set -->
<string name="apn_not_set">Not set</string>
<!-- Edit access point label summary text when no value has been set for mvno value. [CHAR LIMIT=NONE]-->
@@ -4644,6 +4646,8 @@
<string name="accessibility_tutorial_dialog_title_volume">Hold volume keys to open</string>
<!-- Title for the accessibility tutorial dialog in accessibility service with triple tap. [CHAR LIMIT=100] -->
<string name="accessibility_tutorial_dialog_title_triple">Triple tap screen to open</string>
+ <!-- Title for the accessibility tutorial dialog in accessibility service with two finger triple tap. [CHAR LIMIT=100] -->
+ <string name="accessibility_tutorial_dialog_title_two_finger_triple">Two finger triple tap screen to open</string>
<!-- Title for the accessibility tutorial dialog in accessibility service with gesture. [CHAR LIMIT=50] -->
<string name="accessibility_tutorial_dialog_title_gesture">Use gesture to open</string>
<!-- Title for the accessibility tutorial dialog in gesture navigation settings. [CHAR LIMIT=50] -->
@@ -4656,6 +4660,8 @@
<string name="accessibility_tutorial_dialog_message_volume">To use this feature, press & hold both volume keys.</string>
<!-- Instruction for the accessibility tutorial dialog in accessibility service with triple tap. [CHAR LIMIT=100] -->
<string name="accessibility_tutorial_dialog_message_triple">To start and stop magnification, triple-tap anywhere on your screen.</string>
+ <!-- Instruction for the accessibility tutorial dialog in accessibility service with two finger triple tap. [CHAR LIMIT=100] -->
+ <string name="accessibility_tutorial_dialog_message_two_finger_triple">To start and stop magnification, triple-tap anywhere on your screen with two fingers.</string>
<!-- Message for the accessibility tutorial dialog when user enables an accessibility service while using gesture navigation and touch exploration is not enabled. [CHAR LIMIT=NONE] -->
<string name="accessibility_tutorial_dialog_message_gesture">To use this feature, swipe up from the bottom of the screen with 2 fingers.\n\nTo switch between features, swipe up with 2 fingers and hold.</string>
<!-- Message for the accessibility tutorial dialog when user enables an accessibility service while using gesture navigation and touch exploration is enabled. [CHAR LIMIT=NONE] -->
@@ -5430,6 +5436,10 @@
<!-- Category title for battery background settings in power usage detail page [CHAR LIMIT=NONE] -->
<string name="manager_battery_usage_category_title">Manage battery usage</string>
+ <!-- Title for allow background usage [CHAR LIMIT=NONE] -->
+ <string name="manager_battery_usage_allow_background_usage_title">Allow background usage</string>
+ <!-- Summary for allow background usage [CHAR LIMIT=NONE] -->
+ <string name="manager_battery_usage_allow_background_usage_summary">Enable for real-time updates, disable to save battery</string>
<!-- Title for the battery unrestricted settings [CHAR_LIMIT=40] -->
<string name="manager_battery_usage_unrestricted_title">Unrestricted</string>
<!-- Title for the battery optimized settings [CHAR_LIMIT=40] -->
diff --git a/res/xml/power_background_usage_detail.xml b/res/xml/power_background_usage_detail.xml
new file mode 100644
index 0000000..fb089fd
--- /dev/null
+++ b/res/xml/power_background_usage_detail.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/manager_battery_usage_allow_background_usage_title">
+
+ <com.android.settingslib.widget.LayoutPreference
+ android:key="header_view"
+ android:layout="@layout/settings_entity_header"
+ android:selectable="false"/>
+
+ <com.android.settingslib.widget.MainSwitchPreference
+ android:key="allow_background_usage"
+ android:title="@string/manager_battery_usage_allow_background_usage_title"
+ settings:controller="com.android.settings.fuelgauge.AllowBackgroundPreferenceController"/>
+
+ <com.android.settingslib.widget.SelectorWithWidgetPreference
+ android:key="optimized_preference"
+ android:title="@string/manager_battery_usage_optimized_title"
+ android:summary="@string/manager_battery_usage_optimized_summary"
+ settings:controller="com.android.settings.fuelgauge.OptimizedPreferenceController"/>
+
+ <com.android.settingslib.widget.SelectorWithWidgetPreference
+ android:key="unrestricted_preference"
+ android:title="@string/manager_battery_usage_unrestricted_title"
+ android:summary="@string/manager_battery_usage_unrestricted_summary"
+ settings:controller="com.android.settings.fuelgauge.UnrestrictedPreferenceController"/>
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="app_usage_footer_preference"
+ android:title="@string/manager_battery_usage_footer"
+ android:selectable="false"
+ settings:searchable="false"/>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml
index 7b92f99..f3b30b6 100644
--- a/res/xml/power_usage_detail.xml
+++ b/res/xml/power_usage_detail.xml
@@ -50,30 +50,11 @@
android:title="@string/manager_battery_usage_category_title"
android:key="manage_battery_usage_category">
- <com.android.settingslib.widget.SelectorWithWidgetPreference
- android:key="unrestricted_pref"
- android:summary="@string/manager_battery_usage_unrestricted_summary"
- android:title="@string/manager_battery_usage_unrestricted_title"
- settings:controller="com.android.settings.fuelgauge.UnrestrictedPreferenceController"/>
-
- <com.android.settingslib.widget.SelectorWithWidgetPreference
- android:key="optimized_pref"
- android:summary="@string/manager_battery_usage_optimized_summary"
- android:title="@string/manager_battery_usage_optimized_title"
- settings:controller="com.android.settings.fuelgauge.OptimizedPreferenceController"/>
-
- <com.android.settingslib.widget.SelectorWithWidgetPreference
- android:key="restricted_pref"
- android:summary="@string/manager_battery_usage_restricted_summary"
- android:title="@string/manager_battery_usage_restricted_title"
- settings:controller="com.android.settings.fuelgauge.RestrictedPreferenceController"/>
+ <com.android.settingslib.PrimarySwitchPreference
+ android:key="allow_background_usage"
+ android:title="@string/manager_battery_usage_allow_background_usage_title"
+ settings:controller="com.android.settings.fuelgauge.AllowBackgroundPreferenceController"/>
</PreferenceCategory>
- <com.android.settingslib.widget.FooterPreference
- android:key="app_usage_footer_preference"
- android:title="@string/manager_battery_usage_footer"
- android:selectable="false"
- settings:searchable="false"/>
-
</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
index ee2dc05..e90ed87 100644
--- a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
+++ b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
@@ -54,6 +54,7 @@
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
+import com.android.server.accessibility.Flags;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.widget.LottieColorUtils;
@@ -411,6 +412,23 @@
return new TutorialPage(type, title, image, indicatorIcon, instruction);
}
+ private static TutorialPage createTwoFingerTripleTapTutorialPage(@NonNull Context context) {
+ // TODO(b/308088945): Update tutorial string and image when UX provides them
+ final int type = UserShortcutType.TWOFINGERTRIPLETAP;
+ final CharSequence title =
+ context.getText(R.string.accessibility_tutorial_dialog_title_two_finger_triple);
+ final View image =
+ createIllustrationViewWithImageRawResource(context,
+ R.raw.a11y_shortcut_type_triple_tap);
+ final CharSequence instruction =
+ context.getText(R.string.accessibility_tutorial_dialog_message_two_finger_triple);
+ final ImageView indicatorIcon =
+ createImageView(context, R.drawable.ic_accessibility_page_indicator);
+ indicatorIcon.setEnabled(false);
+
+ return new TutorialPage(type, title, image, indicatorIcon, instruction);
+ }
+
@VisibleForTesting
static List<TutorialPage> createShortcutTutorialPages(@NonNull Context context,
int shortcutTypes) {
@@ -427,6 +445,13 @@
tutorialPages.add(createTripleTapTutorialPage(context));
}
+ if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
+ if ((shortcutTypes & UserShortcutType.TWOFINGERTRIPLETAP)
+ == UserShortcutType.TWOFINGERTRIPLETAP) {
+ tutorialPages.add(createTwoFingerTripleTapTutorialPage(context));
+ }
+ }
+
return tutorialPages;
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
index b9ef8f4..b3b7a2c 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
@@ -75,6 +75,8 @@
mMainSwitchBar = activity.getSwitchBar();
mMainSwitchBar.setTitle(getText(R.string.audio_sharing_switch_title));
mSwitchBarController = new AudioSharingSwitchBarController(activity, mMainSwitchBar);
+ mSwitchBarController.init(this);
+ getSettingsLifecycle().addObserver(mSwitchBarController);
mMainSwitchBar.show();
}
}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceAdapter.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceAdapter.java
new file mode 100644
index 0000000..6d5b693
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDeviceAdapter.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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.connecteddevice.audiosharing;
+
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.android.internal.widget.RecyclerView;
+import com.android.settings.R;
+
+import java.util.ArrayList;
+
+public class AudioSharingDeviceAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+
+ private static final String TAG = "AudioSharingDeviceAdapter";
+ private final ArrayList<String> mDevices;
+ private final OnClickListener mOnClickListener;
+
+ public AudioSharingDeviceAdapter(ArrayList<String> devices, OnClickListener listener) {
+ mDevices = devices;
+ mOnClickListener = listener;
+ }
+
+ private class AudioSharingDeviceViewHolder extends RecyclerView.ViewHolder {
+ private final Button mButtonView;
+
+ AudioSharingDeviceViewHolder(View view) {
+ super(view);
+ mButtonView = view.findViewById(R.id.device_button);
+ }
+
+ public void bindView(int position) {
+ if (mButtonView != null) {
+ mButtonView.setText(mDevices.get(position));
+ mButtonView.setOnClickListener(v -> mOnClickListener.onClick(position));
+ } else {
+ Log.w(TAG, "bind view skipped due to button view is null");
+ }
+ }
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view =
+ LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.audio_sharing_device_item, parent, false);
+ return new AudioSharingDeviceViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ ((AudioSharingDeviceViewHolder) holder).bindView(position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mDevices.size();
+ }
+
+ public interface OnClickListener {
+ /** Called when an item has been clicked. */
+ void onClick(int position);
+ }
+}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java
new file mode 100644
index 0000000..5b99907
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 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.connecteddevice.audiosharing;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.internal.widget.LinearLayoutManager;
+import com.android.internal.widget.RecyclerView;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.flags.Flags;
+
+import java.util.ArrayList;
+
+public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
+ private static final String TAG = "AudioSharingDialog";
+
+ private View mRootView;
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DIALOG_START_AUDIO_SHARING;
+ }
+
+ /**
+ * Display the {@link AudioSharingDialogFragment} dialog.
+ *
+ * @param host The Fragment this dialog will be hosted.
+ */
+ public static void show(Fragment host) {
+ if (!Flags.enableLeAudioSharing()) return;
+ final FragmentManager manager = host.getChildFragmentManager();
+ if (manager.findFragmentByTag(TAG) == null) {
+ final AudioSharingDialogFragment dialog = new AudioSharingDialogFragment();
+ dialog.show(manager, TAG);
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final AlertDialog.Builder builder =
+ new AlertDialog.Builder(getActivity()).setTitle("Share audio");
+ mRootView =
+ LayoutInflater.from(builder.getContext())
+ .inflate(R.layout.dialog_audio_sharing, /* parent= */ null);
+ // TODO: use real subtitle according to device count.
+ TextView subTitle1 = mRootView.findViewById(R.id.share_audio_subtitle1);
+ TextView subTitle2 = mRootView.findViewById(R.id.share_audio_subtitle2);
+ subTitle1.setText("2 devices connected");
+ subTitle2.setText("placeholder");
+ RecyclerView recyclerView = mRootView.findViewById(R.id.btn_list);
+ // TODO: use real audio sharing device list.
+ ArrayList<String> devices = new ArrayList<>();
+ devices.add("Buds 1");
+ devices.add("Buds 2");
+ recyclerView.setAdapter(
+ new AudioSharingDeviceAdapter(
+ devices,
+ (int position) -> {
+ // TODO: add on click callback.
+ }));
+ recyclerView.setLayoutManager(
+ new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
+ return builder.setView(mRootView).create();
+ }
+}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
index 1400720..a375a3c 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingSwitchBarController.java
@@ -17,24 +17,30 @@
package com.android.settings.connecteddevice.audiosharing;
import android.content.Context;
+import android.util.Log;
import android.widget.Switch;
import androidx.annotation.NonNull;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.flags.Flags;
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settingslib.widget.OnMainSwitchChangeListener;
-public class AudioSharingSwitchBarController
+public class AudioSharingSwitchBarController extends BasePreferenceController
implements DefaultLifecycleObserver, OnMainSwitchChangeListener {
-
private static final String TAG = "AudioSharingSwitchBarCtl";
+ private static final String PREF_KEY = "audio_sharing_main_switch";
private final Context mContext;
private final SettingsMainSwitchBar mSwitchBar;
+ private DashboardFragment mFragment;
AudioSharingSwitchBarController(Context context, SettingsMainSwitchBar switchBar) {
+ super(context, PREF_KEY);
mContext = context;
mSwitchBar = switchBar;
mSwitchBar.setChecked(false);
@@ -54,11 +60,32 @@
public void onSwitchChanged(Switch switchView, boolean isChecked) {
// Filter out unnecessary callbacks when switch is disabled.
if (!switchView.isEnabled()) return;
-
if (isChecked) {
- // TODO: start sharing
+ startAudioSharing();
} else {
// TODO: stop sharing
}
}
+
+ @Override
+ public int getAvailabilityStatus() {
+ return Flags.enableLeAudioSharing() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+
+ /**
+ * Initialize the controller.
+ *
+ * @param fragment The fragment to host the {@link AudioSharingSwitchBarController} dialog.
+ */
+ public void init(DashboardFragment fragment) {
+ this.mFragment = fragment;
+ }
+
+ private void startAudioSharing() {
+ if (mFragment != null) {
+ AudioSharingDialogFragment.show(mFragment);
+ } else {
+ Log.w(TAG, "Dialog fail to show due to null fragment.");
+ }
+ }
}
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 82917d2..5262ba9 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -27,10 +27,13 @@
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
@@ -45,14 +48,12 @@
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.HelpUtils;
+import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.Instrumentable;
-import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
import java.util.ArrayList;
import java.util.List;
@@ -67,8 +68,8 @@
*/
public class AdvancedPowerUsageDetail extends DashboardFragment implements
ButtonActionDialogFragment.AppButtonsDialogListener,
- SelectorWithWidgetPreference.OnClickListener {
-
+ Preference.OnPreferenceClickListener,
+ Preference.OnPreferenceChangeListener {
public static final String TAG = "AdvancedPowerDetail";
public static final String EXTRA_UID = "extra_uid";
public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
@@ -85,19 +86,16 @@
public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
private static final String KEY_PREF_HEADER = "header_view";
- private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref";
- private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
- private static final String KEY_PREF_RESTRICTED = "restricted_pref";
- private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
- private static final String PACKAGE_NAME_NONE = "none";
-
- private static final String HEADER_SUMMARY_FORMAT = "%s\n(%s)";
+ private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
private static final int REQUEST_UNINSTALL = 0;
private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+ private AppButtonsPreferenceController mAppButtonsPreferenceController;
+ private PowerUsageTimeController mPowerUsageTimeController;
+
@VisibleForTesting
LayoutPreference mHeaderPreference;
@VisibleForTesting
@@ -107,13 +105,7 @@
@VisibleForTesting
BatteryOptimizeUtils mBatteryOptimizeUtils;
@VisibleForTesting
- FooterPreference mFooterPreference;
- @VisibleForTesting
- SelectorWithWidgetPreference mRestrictedPreference;
- @VisibleForTesting
- SelectorWithWidgetPreference mOptimizePreference;
- @VisibleForTesting
- SelectorWithWidgetPreference mUnrestrictedPreference;
+ PrimarySwitchPreference mAllowBackgroundUsagePreference;
@VisibleForTesting
@BatteryOptimizeUtils.OptimizationMode
int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
@@ -122,9 +114,6 @@
@VisibleForTesting
StringBuilder mLogStringBuilder;
- private AppButtonsPreferenceController mAppButtonsPreferenceController;
- private PowerUsageTimeController mPowerUsageTimeController;
-
// A wrapper class to carry LaunchBatteryDetailPage required arguments.
private static final class LaunchBatteryDetailPageArgs {
private String mUsagePercent;
@@ -209,7 +198,7 @@
args.putString(EXTRA_ANOMALY_HINT_PREF_KEY, launchArgs.mAnomalyHintPrefKey);
args.putString(EXTRA_ANOMALY_HINT_TEXT, launchArgs.mAnomalyHintText);
final int userId = launchArgs.mIsUserEntry ? ActivityManager.getCurrentUser()
- : UserHandle.getUserId(launchArgs.mUid);
+ : UserHandle.getUserId(launchArgs.mUid);
new SubSettingLauncher(context)
.setDestination(AdvancedPowerUsageDetail.class.getName())
@@ -257,7 +246,7 @@
super.onCreate(icicle);
final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
- onCreateForTriState(packageName);
+ onCreateBackgroundUsageState(packageName);
mHeaderPreference = findPreference(KEY_PREF_HEADER);
if (packageName != null) {
@@ -271,10 +260,10 @@
initHeader();
mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
- initPreferenceForTriState(getContext());
+ initFooter();
mExecutor.execute(() -> {
- String packageName =
- getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
+ final String packageName = BatteryUtils
+ .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action(
getContext(),
@@ -288,11 +277,10 @@
public void onPause() {
super.onPause();
- final int selectedPreference = getSelectedPreference();
-
notifyBackupManager();
- mLogStringBuilder.append(", onPause mode = ").append(selectedPreference);
- logMetricCategory(selectedPreference);
+ final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
+ mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
+ logMetricCategory(currentOptimizeMode);
mExecutor.execute(() -> {
BatteryOptimizeLogUtils.writeLog(
@@ -302,7 +290,7 @@
mBatteryOptimizeUtils.getPackageName(), UserHandle.myUserId()),
mLogStringBuilder.toString());
});
- Log.d(TAG, "Leave with mode: " + selectedPreference);
+ Log.d(TAG, "Leave with mode: " + currentOptimizeMode);
}
@VisibleForTesting
@@ -353,33 +341,28 @@
}
@VisibleForTesting
- void initPreferenceForTriState(Context context) {
+ void initFooter() {
final String stateString;
- final String footerString;
+ final String detailInfoString;
+ final Context context = getContext();
if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
// Present optimized only string when the package name is invalid.
stateString = context.getString(R.string.manager_battery_usage_optimized_only);
- footerString = context.getString(
- R.string.manager_battery_usage_footer_limited, stateString);
+ detailInfoString =
+ context.getString(R.string.manager_battery_usage_footer_limited, stateString);
} else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
// Present unrestricted only string when the package is system or default active app.
stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
- footerString = context.getString(
- R.string.manager_battery_usage_footer_limited, stateString);
+ detailInfoString =
+ context.getString(R.string.manager_battery_usage_footer_limited, stateString);
} else {
// Present default string to normal app.
- footerString = context.getString(R.string.manager_battery_usage_footer);
+ detailInfoString =
+ context.getString(
+ R.string.manager_battery_usage_allow_background_usage_summary);
}
- mFooterPreference.setTitle(footerString);
- final Intent helpIntent = HelpUtils.getHelpIntent(context, context.getString(
- R.string.help_url_app_usage_settings), /*backupContext=*/ "");
- if (helpIntent != null) {
- mFooterPreference.setLearnMoreAction(v ->
- startActivityForResult(helpIntent, /*requestCode=*/ 0));
- mFooterPreference.setLearnMoreText(
- context.getString(R.string.manager_battery_usage_link_a11y));
- }
+ mAllowBackgroundUsagePreference.setSummary(detailInfoString);
}
@Override
@@ -412,9 +395,7 @@
controllers.add(mPowerUsageTimeController);
}
controllers.add(mAppButtonsPreferenceController);
- controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
- controllers.add(new OptimizedPreferenceController(context, uid, packageName));
- controllers.add(new RestrictedPreferenceController(context, uid, packageName));
+ controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
return controllers;
}
@@ -435,34 +416,45 @@
}
@Override
- public void onRadioButtonClicked(SelectorWithWidgetPreference selected) {
- final String selectedKey = selected.getKey();
- updatePreferenceState(mUnrestrictedPreference, selectedKey);
- updatePreferenceState(mOptimizePreference, selectedKey);
- updatePreferenceState(mRestrictedPreference, selectedKey);
- mBatteryOptimizeUtils.setAppUsageState(getSelectedPreference(), Action.APPLY);
+ public boolean onPreferenceClick(Preference preference) {
+ if (!(preference instanceof PrimarySwitchPreference)
+ || !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
+ return false;
+ }
+ PowerBackgroundUsageDetail.startPowerBackgroundUsageDetailPage(
+ getContext(), getArguments());
+ return true;
}
- private void updatePreferenceState(SelectorWithWidgetPreference preference,
- String selectedKey) {
- preference.setChecked(selectedKey.equals(preference.getKey()));
+ @Override
+ public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
+ if (!(preference instanceof PrimarySwitchPreference)
+ || !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
+ return false;
+ }
+ if (newValue instanceof Boolean) {
+ final boolean isAllowBackgroundUsage = (boolean) newValue;
+ mBatteryOptimizeUtils.setAppUsageState(
+ isAllowBackgroundUsage
+ ? BatteryOptimizeUtils.MODE_OPTIMIZED
+ : BatteryOptimizeUtils.MODE_RESTRICTED,
+ Action.APPLY);
+ }
+ return true;
}
- private void logMetricCategory(int selectedKey) {
- if (selectedKey == mOptimizationMode) {
+ private void logMetricCategory(int currentOptimizeMode) {
+ if (currentOptimizeMode == mOptimizationMode) {
return;
}
-
int metricCategory = 0;
- switch (selectedKey) {
+ switch (currentOptimizeMode) {
case BatteryOptimizeUtils.MODE_UNRESTRICTED:
- metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_UNRESTRICTED;
- break;
case BatteryOptimizeUtils.MODE_OPTIMIZED:
- metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED;
+ metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_ALLOW_BACKGROUND;
break;
case BatteryOptimizeUtils.MODE_RESTRICTED:
- metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
+ metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_DISABLE_BACKGROUND;
break;
}
if (metricCategory == 0) {
@@ -470,8 +462,8 @@
}
int finalMetricCategory = metricCategory;
mExecutor.execute(() -> {
- String packageName =
- getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
+ String packageName = BatteryUtils
+ .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action(
/* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
@@ -482,33 +474,15 @@
});
}
- private void onCreateForTriState(String packageName) {
- mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
- mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
- mRestrictedPreference = findPreference(KEY_PREF_RESTRICTED);
- mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
- mUnrestrictedPreference.setOnClickListener(this);
- mOptimizePreference.setOnClickListener(this);
- mRestrictedPreference.setOnClickListener(this);
-
- mBatteryOptimizeUtils = new BatteryOptimizeUtils(
- getContext(), getArguments().getInt(EXTRA_UID), packageName);
- }
-
- private int getSelectedPreference() {
- if (mRestrictedPreference.isChecked()) {
- return BatteryOptimizeUtils.MODE_RESTRICTED;
- } else if (mUnrestrictedPreference.isChecked()) {
- return BatteryOptimizeUtils.MODE_UNRESTRICTED;
- } else if (mOptimizePreference.isChecked()) {
- return BatteryOptimizeUtils.MODE_OPTIMIZED;
- } else {
- return BatteryOptimizeUtils.MODE_UNKNOWN;
+ private void onCreateBackgroundUsageState(String packageName) {
+ mAllowBackgroundUsagePreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
+ if (mAllowBackgroundUsagePreference != null) {
+ mAllowBackgroundUsagePreference.setOnPreferenceClickListener(this);
+ mAllowBackgroundUsagePreference.setOnPreferenceChangeListener(this);
}
- }
- private static String getLoggingPackageName(Context context, String originalPackingName) {
- return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName)
- ? originalPackingName : PACKAGE_NAME_NONE;
+ mBatteryOptimizeUtils =
+ new BatteryOptimizeUtils(
+ getContext(), getArguments().getInt(EXTRA_UID), packageName);
}
}
diff --git a/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java b/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java
new file mode 100644
index 0000000..d722bad
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023 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.fuelgauge;
+
+import android.content.Context;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.PrimarySwitchPreference;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.MainSwitchPreference;
+
+/** Controller to update the app background usage state */
+public class AllowBackgroundPreferenceController extends AbstractPreferenceController
+ implements PreferenceControllerMixin {
+
+ private static final String TAG = "AllowBackgroundPreferenceController";
+
+ @VisibleForTesting static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
+
+ @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+ public AllowBackgroundPreferenceController(Context context, int uid, String packageName) {
+ super(context);
+ mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
+ }
+
+ private void setChecked(Preference preference, boolean checked) {
+ if (preference instanceof PrimarySwitchPreference) {
+ ((PrimarySwitchPreference) preference).setChecked(checked);
+ } else if (preference instanceof MainSwitchPreference) {
+ ((MainSwitchPreference) preference).setChecked(checked);
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ preference.setEnabled(mBatteryOptimizeUtils.isOptimizeModeMutable());
+
+ final boolean isAllowBackground = mBatteryOptimizeUtils.getAppOptimizationMode()
+ != BatteryOptimizeUtils.MODE_RESTRICTED;
+ setChecked(preference, isAllowBackground);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_ALLOW_BACKGROUND_USAGE;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ return getPreferenceKey().equals(preference.getKey());
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
index 7b3a6ad..003f771 100644
--- a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
@@ -147,6 +147,22 @@
}
/**
+ * Return {@code true} if the optimization mode of this package can be changed
+ */
+ public boolean isOptimizeModeMutable() {
+ return !isDisabledForOptimizeModeOnly() && !isSystemOrDefaultApp();
+ }
+
+ /**
+ * Return {@code true} if the optimization mode is mutable and current state is not restricted
+ */
+ public boolean isSelectorPreferenceEnabled() {
+ // Enable the preference if apps are not set into restricted mode, otherwise disable it
+ return isOptimizeModeMutable()
+ && getAppOptimizationMode() != BatteryOptimizeUtils.MODE_RESTRICTED;
+ }
+
+ /**
* Gets the list of installed applications.
*/
public static ArraySet<ApplicationInfo> getInstalledApplications(
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 3b958ae..c38af07 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -88,6 +88,7 @@
public static final String BYPASS_DOCK_DEFENDER_ACTION = "battery.dock.defender.bypass";
private static final String GOOGLE_PLAY_STORE_PACKAGE = "com.android.vending";
+ private static final String PACKAGE_NAME_NONE = "none";
@Retention(RetentionPolicy.SOURCE)
@IntDef({StatusType.SCREEN_USAGE,
@@ -140,6 +141,12 @@
FeatureFactory.getFeatureFactory().getPowerUsageFeatureProvider();
}
+ /** For test to reset single instance. */
+ @VisibleForTesting
+ public void reset() {
+ sInstance = null;
+ }
+
public long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid,
int which) {
if (uid == null) {
@@ -616,6 +623,12 @@
&& GOOGLE_PLAY_STORE_PACKAGE.equals(installSourceInfo.getInitiatingPackageName());
}
+ /** Gets the logging package name. */
+ public static String getLoggingPackageName(Context context, String originalPackingName) {
+ return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName)
+ ? originalPackingName : PACKAGE_NAME_NONE;
+ }
+
/** Gets the latest sticky battery intent from the Android system. */
public static Intent getBatteryIntent(Context context) {
return com.android.settingslib.fuelgauge.BatteryUtils.getBatteryIntent(context);
diff --git a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
index ca75b0e..3fed00c 100644
--- a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
@@ -17,7 +17,6 @@
package com.android.settings.fuelgauge;
import android.content.Context;
-import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -31,8 +30,10 @@
private static final String TAG = "OPTIMIZED_PREF";
- @VisibleForTesting String KEY_OPTIMIZED_PREF = "optimized_pref";
- @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+ @VisibleForTesting
+ static final String KEY_OPTIMIZED_PREF = "optimized_preference";
+ @VisibleForTesting
+ BatteryOptimizeUtils mBatteryOptimizeUtils;
public OptimizedPreferenceController(Context context, int uid, String packageName) {
super(context);
@@ -46,24 +47,12 @@
@Override
public void updateState(Preference preference) {
- if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
- Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
- preference.setEnabled(true);
- ((SelectorWithWidgetPreference) preference).setChecked(true);
- return;
- }
+ preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
- if (mBatteryOptimizeUtils.getAppOptimizationMode()
- == BatteryOptimizeUtils.MODE_OPTIMIZED) {
- Log.d(TAG, "is optimized states");
- ((SelectorWithWidgetPreference) preference).setChecked(true);
- } else {
- ((SelectorWithWidgetPreference) preference).setChecked(false);
- if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
- Log.d(TAG, "is system or default app, disable pref");
- preference.setEnabled(false);
- }
- }
+ final boolean isOptimized = mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()
+ || mBatteryOptimizeUtils.getAppOptimizationMode()
+ == BatteryOptimizeUtils.MODE_OPTIMIZED;
+ ((SelectorWithWidgetPreference) preference).setChecked(isOptimized);
}
@Override
diff --git a/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
new file mode 100644
index 0000000..3bf4562
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2023 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.fuelgauge;
+
+
+import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+
+import android.app.Activity;
+import android.app.backup.BackupManager;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Switch;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.HelpUtils;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.LayoutPreference;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.OnMainSwitchChangeListener;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Allow background usage fragment for each app
+ */
+public class PowerBackgroundUsageDetail extends DashboardFragment implements
+ SelectorWithWidgetPreference.OnClickListener,
+ OnMainSwitchChangeListener {
+ private static final String TAG = "PowerBackgroundUsageDetail";
+
+ public static final String EXTRA_UID = "extra_uid";
+ public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
+ public static final String EXTRA_LABEL = "extra_label";
+ public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
+ public static final String EXTRA_ICON_ID = "extra_icon_id";
+ private static final String KEY_PREF_HEADER = "header_view";
+ private static final String KEY_PREF_UNRESTRICTED = "unrestricted_preference";
+ private static final String KEY_PREF_OPTIMIZED = "optimized_preference";
+ private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
+ private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
+
+ private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+
+ @VisibleForTesting
+ LayoutPreference mHeaderPreference;
+ @VisibleForTesting
+ ApplicationsState mState;
+ @VisibleForTesting
+ ApplicationsState.AppEntry mAppEntry;
+ @VisibleForTesting
+ BatteryOptimizeUtils mBatteryOptimizeUtils;
+ @VisibleForTesting
+ SelectorWithWidgetPreference mOptimizePreference;
+ @VisibleForTesting
+ SelectorWithWidgetPreference mUnrestrictedPreference;
+ @VisibleForTesting
+ MainSwitchPreference mMainSwitchPreference;
+ @VisibleForTesting
+ FooterPreference mFooterPreference;
+ @VisibleForTesting
+ BackupManager mBackupManager;
+ @VisibleForTesting
+ StringBuilder mLogStringBuilder;
+ @VisibleForTesting
+ @BatteryOptimizeUtils.OptimizationMode
+ int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ mState = ApplicationsState.getInstance(getActivity().getApplication());
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
+ onCreateBackgroundUsageState(packageName);
+ mHeaderPreference = findPreference(KEY_PREF_HEADER);
+
+ if (packageName != null) {
+ mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ initHeader();
+ mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
+ initFooter();
+ mExecutor.execute(() -> {
+ String packageName = BatteryUtils
+ .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
+ FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
+ .action(
+ getContext(),
+ SettingsEnums.OPEN_APP_BATTERY_USAGE,
+ packageName);
+ });
+ mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ notifyBackupManager();
+ final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
+ mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
+ logMetricCategory(currentOptimizeMode);
+
+ mExecutor.execute(() -> {
+ BatteryOptimizeLogUtils.writeLog(
+ getContext().getApplicationContext(),
+ Action.LEAVE,
+ BatteryOptimizeLogUtils.getPackageNameWithUserId(
+ mBatteryOptimizeUtils.getPackageName(), UserHandle.myUserId()),
+ mLogStringBuilder.toString());
+ });
+ Log.d(TAG, "Leave with mode: " + currentOptimizeMode);
+ }
+
+ @Override
+ public void onRadioButtonClicked(SelectorWithWidgetPreference selected) {
+ final String selectedKey = selected == null ? null : selected.getKey();
+ updateSelectorPreferenceState(mUnrestrictedPreference, selectedKey);
+ updateSelectorPreferenceState(mOptimizePreference, selectedKey);
+ mBatteryOptimizeUtils.setAppUsageState(getSelectedPreference(), Action.APPLY);
+ }
+
+ @Override
+ public void onSwitchChanged(Switch switchView, boolean isChecked) {
+ mMainSwitchPreference.setChecked(isChecked);
+ updateSelectorPreference(isChecked);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND;
+ }
+
+ @Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ final Bundle bundle = getArguments();
+ final int uid = bundle.getInt(EXTRA_UID, 0);
+ final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
+
+ controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
+ controllers.add(new OptimizedPreferenceController(context, uid, packageName));
+ controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
+
+ return controllers;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.power_background_usage_detail;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @VisibleForTesting
+ void updateSelectorPreference(boolean isEnabled) {
+ mOptimizePreference.setEnabled(isEnabled);
+ mUnrestrictedPreference.setEnabled(isEnabled);
+ onRadioButtonClicked(isEnabled ? mOptimizePreference : null);
+ }
+
+ @VisibleForTesting
+ void notifyBackupManager() {
+ if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
+ final BackupManager backupManager = mBackupManager != null
+ ? mBackupManager : new BackupManager(getContext());
+ backupManager.dataChanged();
+ }
+ }
+
+ @VisibleForTesting
+ int getSelectedPreference() {
+ if (!mMainSwitchPreference.isChecked()) {
+ return BatteryOptimizeUtils.MODE_RESTRICTED;
+ } else if (mUnrestrictedPreference.isChecked()) {
+ return BatteryOptimizeUtils.MODE_UNRESTRICTED;
+ } else if (mOptimizePreference.isChecked()) {
+ return BatteryOptimizeUtils.MODE_OPTIMIZED;
+ } else {
+ return BatteryOptimizeUtils.MODE_UNKNOWN;
+ }
+ }
+
+ static void startPowerBackgroundUsageDetailPage(
+ Context context, Bundle args) {
+ new SubSettingLauncher(context)
+ .setDestination(PowerBackgroundUsageDetail.class.getName())
+ .setArguments(args)
+ .setSourceMetricsCategory(SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND)
+ .launch();
+ }
+
+ @VisibleForTesting
+ void initHeader() {
+ final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
+ final Activity context = getActivity();
+ final Bundle bundle = getArguments();
+ EntityHeaderController controller = EntityHeaderController
+ .newInstance(context, this, appSnippet)
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
+ EntityHeaderController.ActionType.ACTION_NONE);
+
+ if (mAppEntry == null) {
+ controller.setLabel(bundle.getString(EXTRA_LABEL));
+
+ final int iconId = bundle.getInt(EXTRA_ICON_ID, 0);
+ if (iconId == 0) {
+ controller.setIcon(context.getPackageManager().getDefaultActivityIcon());
+ } else {
+ controller.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
+ }
+ } else {
+ mState.ensureIcon(mAppEntry);
+ controller.setLabel(mAppEntry);
+ controller.setIcon(mAppEntry);
+ controller.setIsInstantApp(AppUtils.isInstant(mAppEntry.info));
+ }
+
+ controller.done(true /* rebindActions */);
+ }
+
+ @VisibleForTesting
+ void initFooter() {
+ final String stateString;
+ final String footerString;
+ final Context context = getContext();
+
+ if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
+ // Present optimized only string when the package name is invalid.
+ stateString = context.getString(R.string.manager_battery_usage_optimized_only);
+ footerString = context.getString(
+ R.string.manager_battery_usage_footer_limited, stateString);
+ } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+ // Present unrestricted only string when the package is system or default active app.
+ stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
+ footerString = context.getString(
+ R.string.manager_battery_usage_footer_limited, stateString);
+ } else {
+ // Present default string to normal app.
+ footerString = context.getString(R.string.manager_battery_usage_footer);
+ }
+ mFooterPreference.setTitle(footerString);
+ final Intent helpIntent = HelpUtils.getHelpIntent(context, context.getString(
+ R.string.help_url_app_usage_settings), /*backupContext=*/ "");
+ if (helpIntent != null) {
+ mFooterPreference.setLearnMoreAction(v ->
+ startActivityForResult(helpIntent, /*requestCode=*/ 0));
+ mFooterPreference.setLearnMoreText(
+ context.getString(R.string.manager_battery_usage_link_a11y));
+ }
+ }
+
+ private void onCreateBackgroundUsageState(String packageName) {
+ mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
+ mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
+ mMainSwitchPreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
+ mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
+
+ mOptimizePreference.setOnClickListener(this);
+ mUnrestrictedPreference.setOnClickListener(this);
+ mMainSwitchPreference.addOnSwitchChangeListener(this);
+
+ mBatteryOptimizeUtils = new BatteryOptimizeUtils(
+ getContext(), getArguments().getInt(EXTRA_UID), packageName);
+ }
+
+ private void updateSelectorPreferenceState(SelectorWithWidgetPreference preference,
+ String selectedKey) {
+ preference.setChecked(TextUtils.equals(selectedKey, preference.getKey()));
+ }
+
+ private void logMetricCategory(int currentOptimizeMode) {
+ if (currentOptimizeMode == mOptimizationMode) {
+ return;
+ }
+ int metricCategory = 0;
+ switch (currentOptimizeMode) {
+ case BatteryOptimizeUtils.MODE_UNRESTRICTED:
+ metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_UNRESTRICTED;
+ break;
+ case BatteryOptimizeUtils.MODE_OPTIMIZED:
+ metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED;
+ break;
+ case BatteryOptimizeUtils.MODE_RESTRICTED:
+ metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
+ break;
+ }
+ if (metricCategory == 0) {
+ return;
+ }
+ int finalMetricCategory = metricCategory;
+ mExecutor.execute(() -> {
+ String packageName = BatteryUtils
+ .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
+ FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
+ .action(
+ /* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
+ /* action */ finalMetricCategory,
+ /* pageId */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
+ packageName,
+ getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT));
+ });
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
deleted file mode 100644
index 7db77f1..0000000
--- a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2021 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.fuelgauge;
-
-import android.content.Context;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-public class RestrictedPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin {
-
- private static final String TAG = "RESTRICTED_PREF";
-
- @VisibleForTesting String KEY_RESTRICTED_PREF = "restricted_pref";
- @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
-
- public RestrictedPreferenceController(Context context, int uid, String packageName) {
- super(context);
- mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
- }
-
- @Override
- public void updateState(Preference preference) {
-
- if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
- Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
- preference.setEnabled(false);
- return;
- } else {
- preference.setEnabled(true);
- }
-
- if (mBatteryOptimizeUtils.getAppOptimizationMode()
- == BatteryOptimizeUtils.MODE_RESTRICTED) {
- Log.d(TAG, "is restricted states");
- ((SelectorWithWidgetPreference) preference).setChecked(true);
- } else {
- ((SelectorWithWidgetPreference) preference).setChecked(false);
- if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
- Log.d(TAG, "is system or default app, disable pref");
- preference.setEnabled(false);
- }
- }
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_RESTRICTED_PREF;
- }
-
- @Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- return getPreferenceKey().equals(preference.getKey());
- }
-}
diff --git a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
index 4578723..b06b7e2 100644
--- a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
@@ -17,7 +17,6 @@
package com.android.settings.fuelgauge;
import android.content.Context;
-import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -31,7 +30,9 @@
private static final String TAG = "UNRESTRICTED_PREF";
- @VisibleForTesting String KEY_UNRESTRICTED_PREF = "unrestricted_pref";
+ @VisibleForTesting
+ static final String KEY_UNRESTRICTED_PREF = "unrestricted_preference";
+
@VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
public UnrestrictedPreferenceController(Context context, int uid, String packageName) {
@@ -41,26 +42,11 @@
@Override
public void updateState(Preference preference) {
+ preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
- if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
- Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
- preference.setEnabled(false);
- return;
- } else {
- preference.setEnabled(true);
- }
-
- if (mBatteryOptimizeUtils.getAppOptimizationMode()
- == BatteryOptimizeUtils.MODE_UNRESTRICTED) {
- Log.d(TAG, "is unrestricted states");
- ((SelectorWithWidgetPreference) preference).setChecked(true);
- } else {
- ((SelectorWithWidgetPreference) preference).setChecked(false);
- if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
- Log.d(TAG, "is system or default app, disable pref");
- preference.setEnabled(false);
- }
- }
+ final boolean isUnrestricted = mBatteryOptimizeUtils.getAppOptimizationMode()
+ == BatteryOptimizeUtils.MODE_UNRESTRICTED;
+ ((SelectorWithWidgetPreference) preference).setChecked(isUnrestricted);
}
@Override
diff --git a/src/com/android/settings/network/EnableMultiSimSidecar.java b/src/com/android/settings/network/EnableMultiSimSidecar.java
index aefd55f..6bc38ef 100644
--- a/src/com/android/settings/network/EnableMultiSimSidecar.java
+++ b/src/com/android/settings/network/EnableMultiSimSidecar.java
@@ -171,8 +171,11 @@
}
int activePorts = 0;
for (UiccSlotInfo slotInfo : slotsInfo) {
+ if (slotInfo == null) {
+ continue;
+ }
for (UiccPortInfo portInfo : slotInfo.getPorts()) {
- if (slotInfo != null && portInfo.isActive()) {
+ if (portInfo.isActive()) {
activePorts++;
}
}
@@ -189,8 +192,11 @@
}
Set<Integer> activeRemovableLogicalSlotIds = new ArraySet<>();
for (UiccSlotInfo info : infos) {
- for (UiccPortInfo portInfo :info.getPorts()) {
- if (info != null && portInfo.isActive() && info.isRemovable()) {
+ if (info == null) {
+ continue;
+ }
+ for (UiccPortInfo portInfo : info.getPorts()) {
+ if (portInfo.isActive() && info.isRemovable()) {
activeRemovableLogicalSlotIds.add(portInfo.getLogicalSlotIndex());
}
}
diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java
index 54c571b..f69b63f 100644
--- a/src/com/android/settings/network/MobileNetworkRepository.java
+++ b/src/com/android/settings/network/MobileNetworkRepository.java
@@ -378,11 +378,11 @@
return mMobileNetworkInfoDao.queryMobileNetworkInfoBySubId(subId);
}
- private void getUiccInfoBySubscriptionInfo(UiccSlotInfo[] uiccSlotInfos,
+ private void getUiccInfoBySubscriptionInfo(@NonNull UiccSlotInfo[] uiccSlotInfos,
SubscriptionInfo subInfo) {
for (int i = 0; i < uiccSlotInfos.length; i++) {
UiccSlotInfo curSlotInfo = uiccSlotInfos[i];
- if (curSlotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT) {
+ if (curSlotInfo != null && curSlotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT) {
final int index = i;
mIsEuicc = curSlotInfo.getIsEuicc();
mCardState = curSlotInfo.getCardStateInfo();
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index bc271ca..b4de224 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -175,10 +175,6 @@
private static final String EXTRA_START_CONNECT_SSID = "wifi_start_connect_ssid";
private String mOpenSsid;
- private static boolean isVerboseLoggingEnabled() {
- return WifiPickerTracker.isVerboseLoggingEnabled();
- }
-
private boolean mIsViewLoading;
@VisibleForTesting
final Runnable mRemoveLoadingRunnable = () -> {
@@ -840,7 +836,7 @@
}
final int wifiState = mWifiPickerTracker.getWifiState();
- if (isVerboseLoggingEnabled()) {
+ if (mWifiPickerTracker.isVerboseLoggingEnabled()) {
Log.i(TAG, "onWifiStateChanged called with wifi state: " + wifiState);
}
diff --git a/src/com/android/settings/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java
index 49a1a85..e329c74 100644
--- a/src/com/android/settings/network/UiccSlotUtil.java
+++ b/src/com/android/settings/network/UiccSlotUtil.java
@@ -301,7 +301,8 @@
}
if (slotId == INVALID_PHYSICAL_SLOT_ID) {
for (int i = 0; i < slots.length; i++) {
- if (slots[i].isRemovable()
+ if (slots[i] != null
+ && slots[i].isRemovable()
&& !slots[i].getIsEuicc()
&& !slots[i].getPorts().stream().findFirst().get().isActive()
&& slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_ERROR
@@ -310,8 +311,9 @@
}
}
} else {
- if (slotId >= slots.length || !slots[slotId].isRemovable()) {
- throw new UiccSlotsException("The given slotId is not a removable slot: " + slotId);
+ if (slotId >= slots.length || slots[slotId] == null || !slots[slotId].isRemovable()) {
+ Log.d(TAG, "The given slotId is not a removable slot: " + slotId);
+ return INVALID_PHYSICAL_SLOT_ID;
}
if (!slots[slotId].getPorts().stream().findFirst().get().isActive()) {
return slotId;
diff --git a/src/com/android/settings/network/apn/ApnEditPageProvider.kt b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
index 0e23a0e..81da0bf 100644
--- a/src/com/android/settings/network/apn/ApnEditPageProvider.kt
+++ b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
@@ -96,7 +96,7 @@
getNetworkTypeSelectedOptionsState(apnData.networkType)
}
RegularScaffold(
- title = stringResource(id = R.string.apn_edit),
+ title = if(apnDataInit.newApn) stringResource(id = R.string.apn_add) else stringResource(id = R.string.apn_edit),
actions = {
IconButton(onClick = {
validateAndSaveApnData(
diff --git a/src/com/android/settings/wifi/WifiEntryPreference.java b/src/com/android/settings/wifi/WifiEntryPreference.java
index c78f28c..e1add15 100644
--- a/src/com/android/settings/wifi/WifiEntryPreference.java
+++ b/src/com/android/settings/wifi/WifiEntryPreference.java
@@ -38,7 +38,6 @@
import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.Utils;
import com.android.settingslib.wifi.WifiUtils;
-import com.android.wifitrackerlib.BaseWifiTracker;
import com.android.wifitrackerlib.HotspotNetworkEntry;
import com.android.wifitrackerlib.WifiEntry;
@@ -108,7 +107,7 @@
@Override
public void onBindViewHolder(final PreferenceViewHolder view) {
super.onBindViewHolder(view);
- if (BaseWifiTracker.isVerboseLoggingEnabled()) {
+ if (mWifiEntry.isVerboseSummaryEnabled()) {
TextView summary = (TextView) view.findViewById(android.R.id.summary);
if (summary != null) {
summary.setMaxLines(100);
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
index 5d3557f..d6a2492 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
@@ -32,11 +32,15 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
import androidx.test.core.app.ApplicationProvider;
+import com.android.server.accessibility.Flags;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -59,6 +63,8 @@
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Mock
private DialogInterface.OnClickListener mOnClickListener;
@Mock
@@ -90,6 +96,19 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+ public void createTutorialPages_turnOnTwoFingerTripleTapShortcut_hasOnePage() {
+ mShortcutTypes |= UserShortcutType.TWOFINGERTRIPLETAP;
+
+ final AlertDialog alertDialog =
+ createAccessibilityTutorialDialog(mContext, mShortcutTypes);
+
+ assertThat(createShortcutTutorialPages(mContext,
+ mShortcutTypes)).hasSize(/* expectedSize= */ 1);
+ assertThat(alertDialog).isNotNull();
+ }
+
+ @Test
public void createTutorialPages_turnOnSoftwareShortcut_hasOnePage() {
mShortcutTypes |= UserShortcutType.SOFTWARE;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 9131051..80486cb 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -17,6 +17,7 @@
package com.android.settings.fuelgauge;
import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
+import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import static com.google.common.truth.Truth.assertThat;
@@ -53,13 +54,12 @@
import com.android.settings.testutils.shadow.ShadowActivityManager;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.PrimarySwitchPreference;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.After;
import org.junit.Before;
@@ -95,9 +95,7 @@
private static final long FOREGROUND_SERVICE_TIME_MS = 444;
private static final long FOREGROUND_TIME_MS =
FOREGROUND_ACTIVITY_TIME_MS + FOREGROUND_SERVICE_TIME_MS;
- private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref";
- private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
- private static final String KEY_PREF_RESTRICTED = "restricted_pref";
+ private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private FragmentActivity mActivity;
@@ -127,10 +125,7 @@
private BackupManager mBackupManager;
private Context mContext;
- private FooterPreference mFooterPreference;
- private SelectorWithWidgetPreference mRestrictedPreference;
- private SelectorWithWidgetPreference mOptimizePreference;
- private SelectorWithWidgetPreference mUnrestrictedPreference;
+ private PrimarySwitchPreference mAllowBackgroundUsagePreference;
private AdvancedPowerUsageDetail mFragment;
private SettingsActivity mTestActivity;
private FakeFeatureFactory mFeatureFactory;
@@ -198,14 +193,9 @@
nullable(UserHandle.class));
doAnswer(callable).when(mActivity).startActivity(captor.capture());
- mFooterPreference = new FooterPreference(mContext);
- mRestrictedPreference = new SelectorWithWidgetPreference(mContext);
- mOptimizePreference = new SelectorWithWidgetPreference(mContext);
- mUnrestrictedPreference = new SelectorWithWidgetPreference(mContext);
- mFragment.mFooterPreference = mFooterPreference;
- mFragment.mRestrictedPreference = mRestrictedPreference;
- mFragment.mOptimizePreference = mOptimizePreference;
- mFragment.mUnrestrictedPreference = mUnrestrictedPreference;
+ mAllowBackgroundUsagePreference = new PrimarySwitchPreference(mContext);
+ mAllowBackgroundUsagePreference.setKey(KEY_ALLOW_BACKGROUND_USAGE);
+ mFragment.mAllowBackgroundUsagePreference = mAllowBackgroundUsagePreference;
}
@After
@@ -307,70 +297,60 @@
}
@Test
- public void initPreferenceForTriState_isValidPackageName_hasCorrectString() {
+ public void initFooter_isValidPackageName_hasCorrectString() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
- mFragment.initPreferenceForTriState(mContext);
+ mFragment.initFooter();
- assertThat(mFooterPreference.getTitle().toString())
+ assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
.isEqualTo("This app requires optimized battery usage.");
}
@Test
- public void initPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() {
+ public void initFooter_isSystemOrDefaultApp_hasCorrectString() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- mFragment.initPreferenceForTriState(mContext);
+ mFragment.initFooter();
- assertThat(mFooterPreference.getTitle()
- .toString()).isEqualTo("This app requires unrestricted battery usage.");
+ assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
+ .isEqualTo("This app requires unrestricted battery usage.");
}
@Test
- public void initPreferenceForTriState_hasCorrectString() {
+ public void initFooter_hasCorrectString() {
when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
- mFragment.initPreferenceForTriState(mContext);
+ mFragment.initFooter();
- assertThat(mFooterPreference.getTitle().toString())
- .isEqualTo("Changing how an app uses your battery can affect its performance.");
- }
-
- @Test
- public void onRadioButtonClicked_clickOptimizePref_optimizePreferenceChecked() {
- mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
- mRestrictedPreference.setKey(KEY_PREF_RESTRICTED);
- mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED);
- mFragment.onRadioButtonClicked(mOptimizePreference);
-
- assertThat(mOptimizePreference.isChecked()).isTrue();
- assertThat(mRestrictedPreference.isChecked()).isFalse();
- assertThat(mUnrestrictedPreference.isChecked()).isFalse();
+ assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
+ .isEqualTo("Enable for real-time updates, disable to save battery");
}
@Test
public void onPause_optimizationModeChanged_logPreference()
throws PackageManager.NameNotFoundException, InterruptedException {
final String packageName = "testPackageName";
- final int mode = BatteryOptimizeUtils.MODE_RESTRICTED;
- mFragment.mOptimizationMode = mode;
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
+ final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+ final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+ mFragment.mOptimizationMode = restrictedMode;
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
- mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
- mFragment.onRadioButtonClicked(mOptimizePreference);
+ mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, true);
+ verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
mFragment.onPause();
TimeUnit.SECONDS.sleep(1);
verify(mMetricsFeatureProvider)
.action(
SettingsEnums.OPEN_APP_BATTERY_USAGE,
- SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED,
+ SettingsEnums.ACTION_APP_BATTERY_USAGE_ALLOW_BACKGROUND,
SettingsEnums.OPEN_APP_BATTERY_USAGE,
packageName,
/* consumed battery */ 0);
@@ -379,15 +359,20 @@
@Test
public void onPause_optimizationModeIsNotChanged_notInvokeLogging()
throws PackageManager.NameNotFoundException, InterruptedException {
- final int mode = BatteryOptimizeUtils.MODE_OPTIMIZED;
- mFragment.mOptimizationMode = mode;
- when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
+ final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+ final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+ mFragment.mOptimizationMode = restrictedMode;
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
- mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
- mFragment.onRadioButtonClicked(mOptimizePreference);
+ mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, true);
+ verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
+ mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, false);
+ verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
mFragment.onPause();
TimeUnit.SECONDS.sleep(1);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.java
new file mode 100644
index 0000000..be80e1e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2023 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.fuelgauge;
+
+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.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import com.android.settingslib.widget.MainSwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class AllowBackgroundPreferenceControllerTest {
+ private static final int UID = 12345;
+ private static final String PACKAGE_NAME = "com.android.app";
+
+ private AllowBackgroundPreferenceController mController;
+ private MainSwitchPreference mMainSwitchPreference;
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+ @Mock private PackageManager mMockPackageManager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ Context context = spy(RuntimeEnvironment.application);
+ BatteryUtils.getInstance(context).reset();
+ doReturn(UID)
+ .when(mMockPackageManager)
+ .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
+
+ mController = new AllowBackgroundPreferenceController(context, UID, PACKAGE_NAME);
+ mMainSwitchPreference = new MainSwitchPreference(RuntimeEnvironment.application);
+ mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
+ mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
+ }
+
+ @Test
+ public void testUpdateState_isValidPackage_prefEnabled() {
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
+
+ mController.updateState(mMainSwitchPreference);
+
+ assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isTrue();
+ assertThat(mMainSwitchPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_invalidPackage_prefDisabled() {
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
+
+ mController.updateState(mMainSwitchPreference);
+
+ assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isFalse();
+ assertThat(mMainSwitchPreference.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_RESTRICTED);
+
+ mController.updateState(mMainSwitchPreference);
+
+ assertThat(mMainSwitchPreference.isEnabled()).isFalse();
+ assertThat(mMainSwitchPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_OPTIMIZED);
+
+ mController.updateState(mMainSwitchPreference);
+
+ assertThat(mMainSwitchPreference.isEnabled()).isFalse();
+ assertThat(mMainSwitchPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_isRestrictedStates_prefChecked() {
+ when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_RESTRICTED);
+
+ mController.updateState(mMainSwitchPreference);
+
+ assertThat(mMainSwitchPreference.isEnabled()).isTrue();
+ assertThat(mMainSwitchPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testUpdateState_prefUnchecked() {
+ when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_OPTIMIZED);
+
+ mController.updateState(mMainSwitchPreference);
+
+ assertThat(mMainSwitchPreference.isEnabled()).isTrue();
+ assertThat(mMainSwitchPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
+ mMainSwitchPreference.setKey(
+ AllowBackgroundPreferenceController.KEY_ALLOW_BACKGROUND_USAGE);
+ mController.handlePreferenceTreeClick(mMainSwitchPreference);
+
+ assertThat(mController.handlePreferenceTreeClick(mMainSwitchPreference)).isTrue();
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
+ assertThat(mController.handlePreferenceTreeClick(mMainSwitchPreference)).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
index b8c72ee..350d2ef 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
@@ -121,6 +121,7 @@
mContext = spy(RuntimeEnvironment.application);
mStringWriter = new StringWriter();
mPrintWriter = new PrintWriter(mStringWriter);
+ BatteryUtils.getInstance(mContext).reset();
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
index e2058e7..bab19e5 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
@@ -31,10 +31,8 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.UserHandle;
-import android.os.UserManager;
import com.android.settings.TestUtils;
-import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry;
import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController;
import org.junit.After;
@@ -75,6 +73,7 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+ BatteryUtils.getInstance(mContext).reset();
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(UID).when(mPackageManager)
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
index 71bb998..bfed149 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
@@ -18,8 +18,13 @@
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.when;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.Before;
@@ -37,34 +42,41 @@
private OptimizedPreferenceController mController;
private SelectorWithWidgetPreference mPreference;
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
- @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+ @Mock PackageManager mMockPackageManager;
@Before
- public void setUp() {
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mController = new OptimizedPreferenceController(
- RuntimeEnvironment.application, UID, PACKAGE_NAME);
+ Context context = spy(RuntimeEnvironment.application);
+ BatteryUtils.getInstance(context).reset();
+ doReturn(UID)
+ .when(mMockPackageManager)
+ .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
+
+ mController = new OptimizedPreferenceController(context, UID, PACKAGE_NAME);
mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
- mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+ mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
+ mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
}
@Test
public void testUpdateState_invalidPackage_prefEnabled() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
mController.updateState(mPreference);
- assertThat(mPreference.isEnabled()).isTrue();
+ assertThat(mPreference.isEnabled()).isFalse();
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void testUpdateState_isSystemOrDefaultAppAndOptimizeStates_prefChecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mPreference);
@@ -74,8 +86,8 @@
@Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
mController.updateState(mPreference);
@@ -85,8 +97,8 @@
@Test
public void testUpdateState_isOptimizedStates_prefChecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mPreference);
@@ -96,7 +108,7 @@
@Test
public void testUpdateState_prefUnchecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
mController.updateState(mPreference);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java
new file mode 100644
index 0000000..e6caf78
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2023 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.fuelgauge;
+
+import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
+import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.app.backup.BackupManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.widget.Switch;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.loader.app.LoaderManager;
+
+import com.android.settings.SettingsActivity;
+import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
+import com.android.settings.testutils.shadow.ShadowActivityManager;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
+import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.LayoutPreference;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+ ShadowEntityHeaderController.class,
+ ShadowActivityManager.class,
+ com.android.settings.testutils.shadow.ShadowFragment.class,
+})
+public class PowerBackgroundUsageDetailTest {
+ private static final String APP_LABEL = "app label";
+ private static final String SUMMARY = "summary";
+ private static final int ICON_ID = 123;
+ private static final int UID = 1;
+ private static final String KEY_PREF_UNRESTRICTED = "unrestricted_preference";
+ private static final String KEY_PREF_OPTIMIZED = "optimized_preference";
+ private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
+
+ private Context mContext;
+ private PowerBackgroundUsageDetail mFragment;
+ private FooterPreference mFooterPreference;
+ private MainSwitchPreference mMainSwitchPreference;
+ private SelectorWithWidgetPreference mOptimizePreference;
+ private SelectorWithWidgetPreference mUnrestrictedPreference;
+ private SettingsActivity mTestActivity;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private FragmentActivity mActivity;
+ @Mock
+ private EntityHeaderController mEntityHeaderController;
+ @Mock
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
+ @Mock
+ private LayoutPreference mHeaderPreference;
+ @Mock
+ private ApplicationsState mState;
+ @Mock
+ private Bundle mBundle;
+ @Mock
+ private LoaderManager mLoaderManager;
+ @Mock
+ private ApplicationsState.AppEntry mAppEntry;
+ @Mock
+ private BatteryEntry mBatteryEntry;
+ @Mock
+ private BackupManager mBackupManager;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private AppOpsManager mAppOpsManager;
+ @Mock
+ private Switch mMockSwitch;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getPackageName()).thenReturn("foo");
+
+ mFragment = spy(new PowerBackgroundUsageDetail());
+ doReturn(mContext).when(mFragment).getContext();
+ doReturn(mActivity).when(mFragment).getActivity();
+ doReturn(SUMMARY).when(mFragment).getString(anyInt());
+ doReturn(APP_LABEL).when(mBundle).getString(nullable(String.class));
+ when(mFragment.getArguments()).thenReturn(mBundle);
+ doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+
+ ShadowEntityHeaderController.setUseMock(mEntityHeaderController);
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setButtonActions(anyInt(), anyInt());
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setIcon(nullable(Drawable.class));
+ doReturn(mEntityHeaderController).when(mEntityHeaderController).setIcon(nullable(
+ ApplicationsState.AppEntry.class));
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setLabel(nullable(String.class));
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setLabel(nullable(String.class));
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setLabel(nullable(ApplicationsState.AppEntry.class));
+ doReturn(mEntityHeaderController).when(mEntityHeaderController)
+ .setSummary(nullable(String.class));
+
+ when(mBatteryEntry.getUid()).thenReturn(UID);
+ when(mBatteryEntry.getLabel()).thenReturn(APP_LABEL);
+ mBatteryEntry.mIconId = ICON_ID;
+
+ mFragment.mHeaderPreference = mHeaderPreference;
+ mFragment.mState = mState;
+ mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
+ mFragment.mBackupManager = mBackupManager;
+ mAppEntry.info = mock(ApplicationInfo.class);
+
+ mTestActivity = spy(new SettingsActivity());
+ doReturn(mPackageManager).when(mTestActivity).getPackageManager();
+ doReturn(mPackageManager).when(mActivity).getPackageManager();
+ doReturn(mAppOpsManager).when(mTestActivity).getSystemService(Context.APP_OPS_SERVICE);
+
+ final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+
+ Answer<Void> callable = invocation -> {
+ mBundle = captor.getValue().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
+ System.out.println("mBundle = " + mBundle);
+ return null;
+ };
+ doAnswer(callable).when(mActivity).startActivityAsUser(captor.capture(),
+ nullable(UserHandle.class));
+ doAnswer(callable).when(mActivity).startActivity(captor.capture());
+
+ mFooterPreference = spy(new FooterPreference(mContext));
+ mMainSwitchPreference = spy(new MainSwitchPreference(mContext));
+ mMainSwitchPreference.setKey(KEY_ALLOW_BACKGROUND_USAGE);
+ mOptimizePreference = spy(new SelectorWithWidgetPreference(mContext));
+ mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
+ mUnrestrictedPreference = spy(new SelectorWithWidgetPreference(mContext));
+ mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED);
+ mFragment.mFooterPreference = mFooterPreference;
+ mFragment.mMainSwitchPreference = mMainSwitchPreference;
+ mFragment.mOptimizePreference = mOptimizePreference;
+ mFragment.mUnrestrictedPreference = mUnrestrictedPreference;
+ }
+
+ @After
+ public void reset() {
+ ShadowEntityHeaderController.reset();
+ }
+
+ @Test
+ public void initHeader_NoAppEntry_BuildByBundle() {
+ mFragment.mAppEntry = null;
+ mFragment.initHeader();
+
+ verify(mEntityHeaderController).setIcon(nullable(Drawable.class));
+ verify(mEntityHeaderController).setLabel(APP_LABEL);
+ }
+
+ @Test
+ public void initHeader_HasAppEntry_BuildByAppEntry() {
+ ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+ new InstantAppDataProvider() {
+ @Override
+ public boolean isInstantApp(ApplicationInfo info) {
+ return false;
+ }
+ });
+ mFragment.mAppEntry = mAppEntry;
+ mFragment.initHeader();
+
+ verify(mEntityHeaderController).setIcon(mAppEntry);
+ verify(mEntityHeaderController).setLabel(mAppEntry);
+ verify(mEntityHeaderController).setIsInstantApp(false);
+ }
+
+ @Test
+ public void initHeader_HasAppEntry_InstantApp() {
+ ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+ new InstantAppDataProvider() {
+ @Override
+ public boolean isInstantApp(ApplicationInfo info) {
+ return true;
+ }
+ });
+ mFragment.mAppEntry = mAppEntry;
+ mFragment.initHeader();
+
+ verify(mEntityHeaderController).setIcon(mAppEntry);
+ verify(mEntityHeaderController).setLabel(mAppEntry);
+ verify(mEntityHeaderController).setIsInstantApp(true);
+ }
+
+ @Test
+ public void initFooter_hasCorrectString() {
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
+
+ mFragment.initFooter();
+
+ assertThat(mFooterPreference.getTitle().toString())
+ .isEqualTo("Changing how an app uses your battery can affect its performance.");
+ }
+
+ @Test
+ public void onSwitchChanged_fromUnrestrictedModeSetDisabled_becomeRestrictedMode() {
+ final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+ final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+ mFragment.mOptimizationMode = optimizedMode;
+
+ mFragment.onSwitchChanged(mMockSwitch, /*isChecked=*/ false);
+
+ verify(mOptimizePreference).setEnabled(false);
+ verify(mUnrestrictedPreference).setEnabled(false);
+ verify(mFragment).onRadioButtonClicked(null);
+ verify(mMainSwitchPreference).setChecked(false);
+ assertThat(mFragment.getSelectedPreference()).isEqualTo(restrictedMode);
+ verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
+ }
+
+ @Test
+ public void onSwitchChanged_fromRestrictedModeSetEnabled_becomeOptimizedMode() {
+ final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+ final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+ mFragment.mOptimizationMode = restrictedMode;
+
+ mFragment.onSwitchChanged(mMockSwitch, /*isChecked=*/ true);
+
+ verify(mOptimizePreference).setEnabled(true);
+ verify(mUnrestrictedPreference).setEnabled(true);
+ verify(mFragment).onRadioButtonClicked(mOptimizePreference);
+ verify(mMainSwitchPreference).setChecked(true);
+ verify(mOptimizePreference).setChecked(true);
+ assertThat(mFragment.getSelectedPreference()).isEqualTo(optimizedMode);
+ verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
deleted file mode 100644
index bcddbc2..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2021 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.fuelgauge;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class RestrictedPreferenceControllerTest {
- private static final int UID = 12345;
- private static final String PACKAGE_NAME = "com.android.app";
-
- private RestrictedPreferenceController mController;
- private SelectorWithWidgetPreference mPreference;
-
- @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mController = new RestrictedPreferenceController(
- RuntimeEnvironment.application, UID, PACKAGE_NAME);
- mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
- mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
- }
-
- @Test
- public void testUpdateState_isValidPackage_prefEnabled() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isTrue();
- }
-
- @Test
- public void testUpdateState_invalidPackage_prefDisabled() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isFalse();
- }
-
- @Test
- public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
- BatteryOptimizeUtils.MODE_RESTRICTED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isFalse();
- assertThat(mPreference.isEnabled()).isFalse();
- }
-
- @Test
- public void testUpdateState_isRestrictedStates_prefChecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
- BatteryOptimizeUtils.MODE_RESTRICTED);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void testUpdateState_prefUnchecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isFalse();
- }
-
- @Test
- public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
- mPreference.setKey(mController.KEY_RESTRICTED_PREF);
- mController.handlePreferenceTreeClick(mPreference);
-
- assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
- }
-
- @Test
- public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
- assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
index 9bed9ba..5489196 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
@@ -18,8 +18,13 @@
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.when;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
import com.android.settingslib.widget.SelectorWithWidgetPreference;
import org.junit.Before;
@@ -37,42 +42,53 @@
private UnrestrictedPreferenceController mController;
private SelectorWithWidgetPreference mPreference;
+ private BatteryOptimizeUtils mBatteryOptimizeUtils;
- @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+ @Mock PackageManager mMockPackageManager;
@Before
- public void setUp() {
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mController = new UnrestrictedPreferenceController(
- RuntimeEnvironment.application, UID, PACKAGE_NAME);
+ Context context = spy(RuntimeEnvironment.application);
+ BatteryUtils.getInstance(context).reset();
+ doReturn(UID)
+ .when(mMockPackageManager)
+ .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
+
+ mController = new UnrestrictedPreferenceController(context, UID, PACKAGE_NAME);
mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
- mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+ mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
+ mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
}
@Test
public void testUpdateState_isValidPackage_prefEnabled() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mController.updateState(mPreference);
+ assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isTrue();
assertThat(mPreference.isEnabled()).isTrue();
}
@Test
public void testUpdateState_invalidPackage_prefDisabled() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
mController.updateState(mPreference);
+ assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void testUpdateState_isSystemOrDefaultAppAndUnrestrictedStates_prefChecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
- when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_UNRESTRICTED);
mController.updateState(mPreference);
@@ -82,32 +98,38 @@
@Test
public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mPreference);
- assertThat(mPreference.isChecked()).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
+ assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void testUpdateState_isUnrestrictedStates_prefChecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
- when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
BatteryOptimizeUtils.MODE_UNRESTRICTED);
mController.updateState(mPreference);
+ assertThat(mPreference.isEnabled()).isTrue();
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void testUpdateState_prefUnchecked() {
- when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+ when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
+ when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+ BatteryOptimizeUtils.MODE_OPTIMIZED);
mController.updateState(mPreference);
+ assertThat(mPreference.isEnabled()).isTrue();
assertThat(mPreference.isChecked()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
index ae726b7..f43feec 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
@@ -82,6 +82,7 @@
MockitoAnnotations.initMocks(this);
ShadowUserHandle.reset();
mContext = spy(RuntimeEnvironment.application);
+ BatteryUtils.getInstance(mContext).reset();
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mMockUserManager).when(mContext).getSystemService(UserManager.class);
doReturn(mMockPackageManager).when(mContext).getPackageManager();
@@ -461,9 +462,6 @@
@Test
public void testIsUninstalledEntry_uninstalledApp_returnTrue() throws Exception {
- doReturn(BatteryUtils.UID_NULL)
- .when(mMockPackageManager)
- .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
final ContentValues values =
getContentValuesWithType(ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put(BatteryHistEntry.KEY_UID, UNINSTALLED_UID);