diff --git a/res/drawable/battery_tips_all_rounded_bg.xml b/res/drawable/battery_tips_all_rounded_bg.xml
new file mode 100644
index 00000000000..4f61f544074
--- /dev/null
+++ b/res/drawable/battery_tips_all_rounded_bg.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/battery_tips_half_rounded_bottom_bg.xml b/res/drawable/battery_tips_half_rounded_bottom_bg.xml
new file mode 100644
index 00000000000..7766de63400
--- /dev/null
+++ b/res/drawable/battery_tips_half_rounded_bottom_bg.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/battery_tips_half_rounded_top_bg.xml b/res/drawable/battery_tips_half_rounded_top_bg.xml
new file mode 100644
index 00000000000..aba1a4fb329
--- /dev/null
+++ b/res/drawable/battery_tips_half_rounded_top_bg.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_battery_charger.xml b/res/drawable/ic_battery_charger.xml
new file mode 100644
index 00000000000..4406a568a3d
--- /dev/null
+++ b/res/drawable/ic_battery_charger.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/res/drawable/ic_battery_tips_close.xml b/res/drawable/ic_battery_tips_close.xml
new file mode 100644
index 00000000000..7ef571b52f9
--- /dev/null
+++ b/res/drawable/ic_battery_tips_close.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
diff --git a/res/drawable/ic_battery_tips_close_icon.xml b/res/drawable/ic_battery_tips_close_icon.xml
new file mode 100644
index 00000000000..b7664740450
--- /dev/null
+++ b/res/drawable/ic_battery_tips_close_icon.xml
@@ -0,0 +1,32 @@
+
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_battery_tips_lightbulb.xml b/res/drawable/ic_battery_tips_lightbulb.xml
new file mode 100644
index 00000000000..f1449f9bb5b
--- /dev/null
+++ b/res/drawable/ic_battery_tips_lightbulb.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_battery_tips_thumb_down.xml b/res/drawable/ic_battery_tips_thumb_down.xml
new file mode 100644
index 00000000000..cd7656b220f
--- /dev/null
+++ b/res/drawable/ic_battery_tips_thumb_down.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_battery_tips_thumb_up.xml b/res/drawable/ic_battery_tips_thumb_up.xml
new file mode 100644
index 00000000000..b1d4cb66c70
--- /dev/null
+++ b/res/drawable/ic_battery_tips_thumb_up.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/battery_tips_card.xml b/res/layout/battery_tips_card.xml
new file mode 100644
index 00000000000..d2edb51c0ab
--- /dev/null
+++ b/res/layout/battery_tips_card.xml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a7a124a32c5..e272c15109b 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -373,6 +373,10 @@
1dp
2dp
+
+ 4dp
+ 24dp
+
174dp
28dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ba5f72db554..8e45f9cd09d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9650,6 +9650,24 @@
Set battery usage for apps
+
+ Optimize
+
+
+ Is this message helpful?
+
+
+ Turn on adaptive brightness to extend battery life
+
+
+ It will help reduce your daily battery drain by 10%
+
+
+ Reduce screen timeout to extend battery life
+
+
+ It will help reduce your daily battery drain by 10%
+
Unrestricted
diff --git a/res/xml/power_usage_advanced.xml b/res/xml/power_usage_advanced.xml
index 2a1a23c78fe..c1294535a74 100644
--- a/res/xml/power_usage_advanced.xml
+++ b/res/xml/power_usage_advanced.xml
@@ -21,6 +21,18 @@
android:title="@string/advanced_battery_title"
settings:keywords="@string/keywords_battery_usage">
+
+
+
+
+
+
mHourlyViewModels;
private OnBatteryUsageUpdatedListener mOnBatteryUsageUpdatedListener;
private OnScreenOnTimeUpdatedListener mOnScreenOnTimeUpdatedListener;
+ private OnBatteryTipsUpdatedListener mOnBatteryTipsUpdatedListener;
private final SettingsActivity mActivity;
private final MetricsFeatureProvider mMetricsFeatureProvider;
@@ -209,6 +224,10 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
mOnScreenOnTimeUpdatedListener = listener;
}
+ void setOnBatteryTipsUpdatedListener(OnBatteryTipsUpdatedListener listener) {
+ mOnBatteryTipsUpdatedListener = listener;
+ }
+
void setBatteryHistoryMap(
final Map> batteryHistoryMap) {
Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
@@ -344,6 +363,10 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
}
mOnBatteryUsageUpdatedListener.onBatteryUsageUpdated(
slotUsageData, getSlotInformation(), isBatteryUsageMapNullOrEmpty());
+
+ if (mOnBatteryTipsUpdatedListener != null) {
+ mOnBatteryTipsUpdatedListener.onBatteryTipsUpdated(null, null);
+ }
}
return true;
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
new file mode 100644
index 00000000000..661d7c8aca3
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreference.java
@@ -0,0 +1,99 @@
+/*
+ * 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.batteryusage;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
+
+import com.google.android.material.button.MaterialButton;
+
+/**
+ * A preference for displaying the battery tips card view.
+ */
+public class BatteryTipsCardPreference extends Preference implements View.OnClickListener {
+
+ private static final String TAG = "BatteryTipsCardPreference";
+
+ private final PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+
+ private MaterialButton mActionButton;
+ private ImageButton mDismissButton;
+ private ImageButton mThumbUpButton;
+ private ImageButton mThumbDownButton;
+ private CharSequence mTitle;
+ private CharSequence mSummary;
+
+ public BatteryTipsCardPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLayoutResource(R.layout.battery_tips_card);
+ setSelectable(false);
+ mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
+ .getPowerUsageFeatureProvider(context);
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ mTitle = title;
+ notifyChanged();
+ }
+
+ @Override
+ public void setSummary(CharSequence summary) {
+ mSummary = summary;
+ notifyChanged();
+ }
+
+ @Override
+ public void onClick(View view) {
+ // TODO: replace with the settings anomaly obtained from detectSettingsAnomaly();
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder view) {
+ super.onBindViewHolder(view);
+
+ ((TextView) view.findViewById(R.id.title)).setText(mTitle);
+ ((TextView) view.findViewById(R.id.summary)).setText(mSummary);
+
+ mActionButton = (MaterialButton) view.findViewById(R.id.action_button);
+ mActionButton.setOnClickListener(this);
+ mDismissButton = (ImageButton) view.findViewById(R.id.dismiss_button);
+ mDismissButton.setOnClickListener(this);
+
+ if (!mPowerUsageFeatureProvider.isBatteryTipsFeedbackEnabled()) {
+ return;
+ }
+ view.findViewById(R.id.tips_card)
+ .setBackgroundResource(R.drawable.battery_tips_half_rounded_top_bg);
+ view.findViewById(R.id.feedback_card).setVisibility(View.VISIBLE);
+
+ mThumbUpButton = (ImageButton) view.findViewById(R.id.thumb_up);
+ mThumbUpButton.setOnClickListener(this);
+ mThumbDownButton = (ImageButton) view.findViewById(R.id.thumb_down);
+ mThumbDownButton.setOnClickListener(this);
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
new file mode 100644
index 00000000000..bcedd4f5794
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java
@@ -0,0 +1,77 @@
+/*
+ * 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.batteryusage;
+
+import android.content.Context;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
+
+/** Controls the update for battery tips card */
+public class BatteryTipsController extends BasePreferenceController {
+
+ private static final String TAG = "BatteryTipsController";
+ private static final String ROOT_PREFERENCE_KEY = "battery_tips_category";
+ private static final String CARD_PREFERENCE_KEY = "battery_tips_card";
+
+ private final PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+
+ private Context mPrefContext;
+ private BatteryTipsCardPreference mCardPreference;
+
+ public BatteryTipsController(Context context) {
+ super(context, ROOT_PREFERENCE_KEY);
+ mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
+ .getPowerUsageFeatureProvider(context);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPrefContext = screen.getContext();
+ mCardPreference = screen.findPreference(CARD_PREFERENCE_KEY);
+ }
+
+ /**
+ * Update the card visibility and contents.
+ * @param title a string not extend 2 lines.
+ * @param summary a string not extend 10 lines.
+ */
+ // TODO: replace parameters with SettingsAnomaly Data Proto
+ public void handleBatteryTipsCardUpdated(String title, String summary) {
+ if (!mPowerUsageFeatureProvider.isBatteryTipsEnabled()) {
+ mCardPreference.setVisible(false);
+ return;
+ }
+ if (title == null || summary == null) {
+ mCardPreference.setVisible(false);
+ return;
+ }
+ mCardPreference.setTitle(title);
+ mCardPreference.setSummary(summary);
+ mCardPreference.setVisible(true);
+ }
+
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
index 920670fa13f..6d14e1c72e4 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiver.java
@@ -83,6 +83,10 @@ public final class BootBroadcastReceiver extends BroadcastReceiver {
recheckIntent.setClass(context, BootBroadcastReceiver.class);
final long delayedTime = getRescheduleTimeForBootAction(context);
mHandler.postDelayed(() -> context.sendBroadcast(recheckIntent), delayedTime);
+
+ // Refreshes the usage source from UsageStatsManager when booting.
+ DatabaseUtils.removeUsageSource(context);
+
BatteryUsageLogUtils.writeLog(context, Action.RECHECK_JOB, "delay:" + delayedTime);
} else if (ACTION_SETUP_WIZARD_FINISHED.equals(action)) {
ElapsedTimeUtils.storeSuwFinishedTimestamp(context, System.currentTimeMillis());
diff --git a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
index 2c98c4bd249..3fc44ccfd9b 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
@@ -17,7 +17,6 @@ package com.android.settings.fuelgauge.batteryusage;
import android.annotation.IntDef;
import android.annotation.Nullable;
-import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStatsManager;
import android.content.ContentValues;
@@ -27,7 +26,6 @@ import android.database.Cursor;
import android.os.BatteryUsageStats;
import android.os.Build;
import android.os.LocaleList;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.text.format.DateFormat;
@@ -67,6 +65,12 @@ public final class ConvertUtils {
public static final int CONSUMER_TYPE_USER_BATTERY = 2;
public static final int CONSUMER_TYPE_SYSTEM_BATTERY = 3;
+ public static final int DEFAULT_USAGE_SOURCE = UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
+ public static final int EMPTY_USAGE_SOURCE = -1;
+
+ @VisibleForTesting
+ static int sUsageSource = EMPTY_USAGE_SOURCE;
+
private ConvertUtils() {
}
@@ -181,8 +185,7 @@ public final class ConvertUtils {
/** Converts to {@link AppUsageEvent} from {@link Event} */
@Nullable
public static AppUsageEvent convertToAppUsageEvent(
- Context context, final IUsageStatsManager usageStatsManager, final Event event,
- final long userId) {
+ Context context, final Event event, final long userId) {
final String packageName = event.getPackageName();
if (packageName == null) {
// See b/190609174: Event package names should never be null, but sometimes they are.
@@ -207,7 +210,7 @@ public final class ConvertUtils {
}
final String effectivePackageName =
- getEffectivePackageName(usageStatsManager, packageName, taskRootPackageName);
+ getEffectivePackageName(context, packageName, taskRootPackageName);
try {
final long uid = context
.getPackageManager()
@@ -323,9 +326,8 @@ public final class ConvertUtils {
*/
@VisibleForTesting
static String getEffectivePackageName(
- final IUsageStatsManager usageStatsManager, final String packageName,
- final String taskRootPackageName) {
- int usageSource = getUsageSource(usageStatsManager);
+ Context context, final String packageName, final String taskRootPackageName) {
+ final int usageSource = getUsageSource(context);
switch (usageSource) {
case UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY:
return !TextUtils.isEmpty(taskRootPackageName)
@@ -370,18 +372,11 @@ public final class ConvertUtils {
}
}
- /**
- * Returns what App Usage Observers will consider the source of usage for an activity.
- *
- * @see UsageStatsManager#getUsageSource()
- */
- private static int getUsageSource(final IUsageStatsManager usageStatsManager) {
- try {
- return usageStatsManager.getUsageSource();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to getUsageSource", e);
- return UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
+ private static int getUsageSource(Context context) {
+ if (sUsageSource == EMPTY_USAGE_SOURCE) {
+ sUsageSource = DatabaseUtils.getUsageSource(context);
}
+ return sUsageSource;
}
private static AppUsageEventType getAppUsageEventType(final int eventType) {
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
index 0f67e6a7a5a..1c851fd4ca9 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
@@ -397,8 +397,8 @@ public class DataProcessManager {
}
// Generates the indexed AppUsagePeriod list data for each corresponding time slot for
// further use.
- mAppUsagePeriodMap = DataProcessor.generateAppUsagePeriodMap(mRawStartTimestamp,
- mHourlyBatteryLevelsPerDay, mAppUsageEventList, mBatteryEventList);
+ mAppUsagePeriodMap = DataProcessor.generateAppUsagePeriodMap(
+ mContext, mHourlyBatteryLevelsPerDay, mAppUsageEventList, mBatteryEventList);
}
private void tryToGenerateFinalDataAndApplyCallback() {
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index 6914c3043ea..badc35935fa 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -32,7 +32,6 @@ import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UidBatteryConsumer;
import android.os.UserBatteryConsumer;
import android.os.UserHandle;
@@ -78,8 +77,6 @@ public final class DataProcessor {
private static final int MIN_DAILY_DATA_SIZE = 2;
private static final int MIN_TIMESTAMP_DATA_SIZE = 2;
private static final int MAX_DIFF_SECONDS_OF_UPPER_TIMESTAMP = 5;
- // Maximum total time value for each hourly slot cumulative data at most 2 hours.
- private static final float TOTAL_HOURLY_TIME_THRESHOLD = DateUtils.HOUR_IN_MILLIS * 2;
private static final long MIN_TIME_SLOT = DateUtils.HOUR_IN_MILLIS * 2;
private static final String MEDIASERVER_PACKAGE_NAME = "mediaserver";
private static final String ANDROID_CORE_APPS_SHARED_USER_ID = "android.uid.shared";
@@ -111,11 +108,6 @@ public final class DataProcessor {
@VisibleForTesting
static Set sTestSystemAppsPackageNames;
- @VisibleForTesting
- static IUsageStatsManager sUsageStatsManager =
- IUsageStatsManager.Stub.asInterface(
- ServiceManager.getService(Context.USAGE_STATS_SERVICE));
-
public static final String CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER =
"CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER";
@@ -271,7 +263,7 @@ public final class DataProcessor {
@Nullable
public static Map>>>>
generateAppUsagePeriodMap(
- final long rawStartTimestamp,
+ Context context,
final List hourlyBatteryLevelsPerDay,
final List appUsageEventList,
final List batteryEventList) {
@@ -305,7 +297,7 @@ public final class DataProcessor {
// The value could be null when there is no data in the hourly slot.
dailyMap.put(
hourlyIndex,
- buildAppUsagePeriodList(hourlyAppUsageEventList, batteryEventList,
+ buildAppUsagePeriodList(context, hourlyAppUsageEventList, batteryEventList,
startTimestamp, endTimestamp));
}
}
@@ -346,8 +338,7 @@ public final class DataProcessor {
break;
}
final AppUsageEvent appUsageEvent =
- ConvertUtils.convertToAppUsageEvent(
- context, sUsageStatsManager, event, userId);
+ ConvertUtils.convertToAppUsageEvent(context, event, userId);
if (appUsageEvent != null) {
numEventsFetched++;
appUsageEventList.add(appUsageEvent);
@@ -661,8 +652,8 @@ public final class DataProcessor {
@VisibleForTesting
@Nullable
static Map>> buildAppUsagePeriodList(
- final List appUsageEvents, final List batteryEventList,
- final long startTime, final long endTime) {
+ Context context, final List appUsageEvents,
+ final List batteryEventList, final long startTime, final long endTime) {
if (appUsageEvents.isEmpty()) {
return null;
}
@@ -702,7 +693,7 @@ public final class DataProcessor {
final AppUsageEvent firstEvent = usageEvents.get(0);
final long eventUserId = firstEvent.getUserId();
final String packageName = getEffectivePackageName(
- sUsageStatsManager,
+ context,
firstEvent.getPackageName(),
firstEvent.getTaskRootPackageName());
usageEvents.addAll(deviceEvents);
@@ -975,7 +966,7 @@ public final class DataProcessor {
final long startTime = DatabaseUtils.getAppUsageStartTimestampOfUser(
context, userID, earliestTimestamp);
return loadAppUsageEventsForUserFromService(
- sUsageStatsManager, startTime, now, userID, callingPackage);
+ DatabaseUtils.sUsageStatsManager, startTime, now, userID, callingPackage);
}
@Nullable
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
index 8d1a2f90991..ea1f3ed9e79 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
@@ -15,6 +15,8 @@
*/
package com.android.settings.fuelgauge.batteryusage;
+import android.app.usage.IUsageStatsManager;
+import android.app.usage.UsageStatsManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -28,6 +30,8 @@ import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.Handler;
import android.os.Looper;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserManager;
import android.util.Log;
@@ -63,6 +67,7 @@ public final class DatabaseUtils {
static final int DATA_RETENTION_INTERVAL_DAY = 9;
static final String KEY_LAST_LOAD_FULL_CHARGE_TIME = "last_load_full_charge_time";
static final String KEY_LAST_UPLOAD_FULL_CHARGE_TIME = "last_upload_full_charge_time";
+ static final String KEY_LAST_USAGE_SOURCE = "last_usage_source";
/** An authority name of the battery content provider. */
public static final String AUTHORITY = "com.android.settings.battery.usage.provider";
@@ -74,8 +79,6 @@ public final class DatabaseUtils {
public static final String BATTERY_STATE_TABLE = "BatteryState";
/** A path name for app usage latest timestamp query. */
public static final String APP_USAGE_LATEST_TIMESTAMP_PATH = "appUsageLatestTimestamp";
- /** A class name for battery usage data provider. */
- public static final String SETTINGS_PACKAGE_PATH = "com.android.settings";
/** Key for query parameter timestamp used in BATTERY_CONTENT_URI **/
public static final String QUERY_KEY_TIMESTAMP = "timestamp";
/** Key for query parameter userid used in APP_USAGE_EVENT_URI **/
@@ -114,6 +117,11 @@ public final class DatabaseUtils {
@VisibleForTesting
static Supplier sFakeSupplier;
+ @VisibleForTesting
+ static IUsageStatsManager sUsageStatsManager =
+ IUsageStatsManager.Stub.asInterface(
+ ServiceManager.getService(Context.USAGE_STATS_SERVICE));
+
private DatabaseUtils() {
}
@@ -468,6 +476,37 @@ public final class DatabaseUtils {
SHARED_PREFS_FILE, Context.MODE_PRIVATE);
}
+ static void removeUsageSource(Context context) {
+ final SharedPreferences sharedPreferences = getSharedPreferences(context);
+ if (sharedPreferences != null && sharedPreferences.contains(KEY_LAST_USAGE_SOURCE)) {
+ sharedPreferences.edit().remove(KEY_LAST_USAGE_SOURCE).apply();
+ }
+ }
+
+ /**
+ * Returns what App Usage Observers will consider the source of usage for an activity.
+ *
+ * @see UsageStatsManager#getUsageSource()
+ */
+ static int getUsageSource(Context context) {
+ final SharedPreferences sharedPreferences = getSharedPreferences(context);
+ if (sharedPreferences != null && sharedPreferences.contains(KEY_LAST_USAGE_SOURCE)) {
+ return sharedPreferences
+ .getInt(KEY_LAST_USAGE_SOURCE, ConvertUtils.DEFAULT_USAGE_SOURCE);
+ }
+ int usageSource = ConvertUtils.DEFAULT_USAGE_SOURCE;
+
+ try {
+ usageSource = sUsageStatsManager.getUsageSource();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to getUsageSource", e);
+ }
+ if (sharedPreferences != null) {
+ sharedPreferences.edit().putInt(KEY_LAST_USAGE_SOURCE, usageSource).apply();
+ }
+ return usageSource;
+ }
+
static void recordDateTime(Context context, String preferenceKey) {
final SharedPreferences sharedPreferences = getSharedPreferences(context);
if (sharedPreferences != null) {
@@ -564,7 +603,7 @@ public final class DatabaseUtils {
private static Map> loadHistoryMapFromContentProvider(
Context context, Uri batteryStateUri) {
- context = DatabaseUtils.getParentContext(context);
+ context = getParentContext(context);
if (context == null) {
return null;
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
index 7c4478e66c6..9a8680e2244 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
@@ -34,6 +34,8 @@ import androidx.loader.content.Loader;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.fuelgauge.BatteryBroadcastReceiver;
+import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
@@ -143,6 +145,16 @@ public class PowerUsageAdvanced extends PowerUsageBase {
controllers.add(screenOnTimeController);
controllers.add(batteryUsageBreakdownController);
setBatteryChartPreferenceController();
+
+ final PowerUsageFeatureProvider powerUsageFeatureProvider =
+ FeatureFactory.getFactory(context).getPowerUsageFeatureProvider(context);
+ if (powerUsageFeatureProvider.isBatteryTipsEnabled()) {
+ BatteryTipsController batteryTipsController = new BatteryTipsController(context);
+ mBatteryChartPreferenceController.setOnBatteryTipsUpdatedListener(
+ batteryTipsController::handleBatteryTipsCardUpdated);
+ controllers.add(batteryTipsController);
+ }
+
return controllers;
}
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index 09d192412ba..3a1532b56e5 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -523,6 +523,7 @@ public class ChooseLockPassword extends SettingsActivity {
setupPasswordRequirementsView(headerLayout);
mPasswordRestrictionView.setLayoutManager(new LinearLayoutManager(getActivity()));
+ mPasswordRestrictionView.setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
mPasswordEntry = view.findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
mPasswordEntry.addTextChangedListener(this);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index 1a43dbbe8d2..c9591a51b08 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -67,6 +67,15 @@ public class PowerUsageFeatureProviderImplTest {
assertThat(mPowerFeatureProvider.isBatteryUsageEnabled()).isTrue();
}
+ @Test
+ public void testIsBatteryTipsEnabled_returnFalse() {
+ assertThat(mPowerFeatureProvider.isBatteryTipsEnabled()).isFalse();
+ }
+
+ @Test
+ public void testIsBatteryTipsFeedbackEnabled_returnTrue() {
+ assertThat(mPowerFeatureProvider.isBatteryTipsFeedbackEnabled()).isTrue();
+ }
@Test
public void testGetBatteryUsageListConsumePowerThreshold_return0() {
assertThat(mPowerFeatureProvider.getBatteryUsageListConsumePowerThreshold()).isEqualTo(0.0);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTipTest.java
index a5f1ab3f531..9f6e4e32a71 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTipTest.java
@@ -85,7 +85,7 @@ public final class IncompatibleChargerTipTest {
@Test
public void getIcon_showIcon() {
assertThat(mIncompatibleChargerTip.getIconId())
- .isEqualTo(R.drawable.ic_battery_alert_theme);
+ .isEqualTo(R.drawable.ic_battery_charger);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
new file mode 100644
index 00000000000..6f9a47416ae
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.batteryusage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public final class BatteryTipsCardPreferenceTest {
+
+ private Context mContext;
+ private BatteryTipsCardPreference mBatteryTipsCardPreference;
+
+ @Before
+ public void setUp() {
+ mContext = spy(RuntimeEnvironment.application);
+ mBatteryTipsCardPreference = new BatteryTipsCardPreference(mContext, /*attrs=*/ null);
+ }
+
+ @Test
+ public void constructor_returnExpectedResult() {
+ assertThat(mBatteryTipsCardPreference.getLayoutResource()).isEqualTo(
+ R.layout.battery_tips_card);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
index aa1ebd7b44c..566df5251d5 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BootBroadcastReceiverTest.java
@@ -22,8 +22,10 @@ import static org.robolectric.Shadows.shadowOf;
import android.app.AlarmManager;
import android.app.Application;
+import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import androidx.test.core.app.ApplicationProvider;
@@ -40,7 +42,6 @@ import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowAlarmManager;
import java.time.Clock;
-import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -65,10 +66,12 @@ public final class BootBroadcastReceiverTest {
BatteryTestUtils.insertDataToBatteryStateTable(
mContext, Clock.systemUTC().millis(), "com.android.systemui");
mDao = database.batteryStateDao();
+ clearSharedPreferences();
}
@After
public void tearDown() {
+ clearSharedPreferences();
mPeriodicJobManager.reset();
}
@@ -82,8 +85,21 @@ public final class BootBroadcastReceiverTest {
@Test
public void onReceive_withBootCompletedIntent_refreshesJob() {
+ final SharedPreferences sharedPreferences = DatabaseUtils.getSharedPreferences(mContext);
+ sharedPreferences
+ .edit()
+ .putInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE,
+ UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY)
+ .apply();
+
mReceiver.onReceive(mContext, new Intent(Intent.ACTION_BOOT_COMPLETED));
+
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNotNull();
+ assertThat(
+ DatabaseUtils
+ .getSharedPreferences(mContext)
+ .contains(DatabaseUtils.KEY_LAST_USAGE_SOURCE))
+ .isFalse();
}
@Test
@@ -133,15 +149,7 @@ public final class BootBroadcastReceiverTest {
BootBroadcastReceiver.ACTION_PERIODIC_JOB_RECHECK);
}
- private void insertExpiredData(int shiftDay) {
- final long expiredTimeInMs =
- Clock.systemUTC().millis() - Duration.ofDays(shiftDay).toMillis();
- BatteryTestUtils.insertDataToBatteryStateTable(
- mContext, expiredTimeInMs - 1, "com.android.systemui");
- BatteryTestUtils.insertDataToBatteryStateTable(
- mContext, expiredTimeInMs, "com.android.systemui");
- // Ensures the testing environment is correct.
- assertThat(mDao.getAllAfter(0)).hasSize(3);
+ private void clearSharedPreferences() {
+ DatabaseUtils.getSharedPreferences(mContext).edit().clear().apply();
}
-
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
index 6b8073b68ee..3cbe8a44d1f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -25,7 +25,6 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.content.ContentValues;
@@ -35,7 +34,6 @@ import android.database.MatrixCursor;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.LocaleList;
-import android.os.RemoteException;
import android.os.UserHandle;
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
@@ -62,14 +60,13 @@ public final class ConvertUtilsTest {
@Mock
private BatteryUsageStats mBatteryUsageStats;
@Mock
- private IUsageStatsManager mUsageStatsManager;
- @Mock
private BatteryEntry mMockBatteryEntry;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+ ConvertUtils.sUsageSource = ConvertUtils.EMPTY_USAGE_SOURCE;
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
}
@@ -302,7 +299,7 @@ public final class ConvertUtilsTest {
final long userId = 2;
final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
- mContext, mUsageStatsManager, event, userId);
+ mContext, event, userId);
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.ACTIVITY_RESUMED);
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
@@ -322,8 +319,8 @@ public final class ConvertUtilsTest {
when(mMockPackageManager.getPackageUidAsUser(any(), anyInt())).thenReturn(1001);
final long userId = 1;
- final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
- mContext, mUsageStatsManager, event, userId);
+ final AppUsageEvent appUsageEvent =
+ ConvertUtils.convertToAppUsageEvent(mContext, event, userId);
assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
@@ -338,8 +335,8 @@ public final class ConvertUtilsTest {
final Event event = new Event();
event.mPackage = null;
- final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
- mContext, mUsageStatsManager, event, /*userId=*/ 0);
+ final AppUsageEvent appUsageEvent =
+ ConvertUtils.convertToAppUsageEvent(mContext, event, /*userId=*/ 0);
assertThat(appUsageEvent).isNull();
}
@@ -354,8 +351,8 @@ public final class ConvertUtilsTest {
.thenThrow(new PackageManager.NameNotFoundException());
final long userId = 1;
- final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
- mContext, mUsageStatsManager, event, userId);
+ final AppUsageEvent appUsageEvent =
+ ConvertUtils.convertToAppUsageEvent(mContext, event, userId);
assertThat(appUsageEvent).isNull();
}
@@ -450,51 +447,47 @@ public final class ConvertUtilsTest {
}
@Test
- public void getEffectivePackageName_currentActivity_returnPackageName() throws RemoteException {
- when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_CURRENT_ACTIVITY);
+ public void getEffectivePackageName_currentActivity_returnPackageName() {
+ ConvertUtils.sUsageSource = USAGE_SOURCE_CURRENT_ACTIVITY;
final String packageName = "com.android.settings1";
final String taskRootPackageName = "com.android.settings2";
assertThat(ConvertUtils.getEffectivePackageName(
- mUsageStatsManager, packageName, taskRootPackageName))
+ mContext, packageName, taskRootPackageName))
.isEqualTo(packageName);
}
@Test
- public void getEffectivePackageName_usageSourceThrowException_returnPackageName()
- throws RemoteException {
- when(mUsageStatsManager.getUsageSource()).thenThrow(new RemoteException());
+ public void getEffectivePackageName_emptyUsageSource_returnPackageName() {
final String packageName = "com.android.settings1";
final String taskRootPackageName = "com.android.settings2";
assertThat(ConvertUtils.getEffectivePackageName(
- mUsageStatsManager, packageName, taskRootPackageName))
+ mContext, packageName, taskRootPackageName))
.isEqualTo(packageName);
}
@Test
- public void getEffectivePackageName_rootActivity_returnTaskRootPackageName()
- throws RemoteException {
- when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
+ public void getEffectivePackageName_rootActivity_returnTaskRootPackageName() {
+ ConvertUtils.sUsageSource = USAGE_SOURCE_TASK_ROOT_ACTIVITY;
final String packageName = "com.android.settings1";
final String taskRootPackageName = "com.android.settings2";
assertThat(ConvertUtils.getEffectivePackageName(
- mUsageStatsManager, packageName, taskRootPackageName))
+ mContext, packageName, taskRootPackageName))
.isEqualTo(taskRootPackageName);
}
@Test
- public void getEffectivePackageName_nullOrEmptyTaskRoot_returnPackageName()
- throws RemoteException {
- when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
+ public void getEffectivePackageName_nullOrEmptyTaskRoot_returnPackageName() {
+ ConvertUtils.sUsageSource = USAGE_SOURCE_TASK_ROOT_ACTIVITY;
final String packageName = "com.android.settings1";
assertThat(ConvertUtils.getEffectivePackageName(
- mUsageStatsManager, packageName, /*taskRootPackageName=*/ null))
+ mContext, packageName, /*taskRootPackageName=*/ null))
.isEqualTo(packageName);
assertThat(ConvertUtils.getEffectivePackageName(
- mUsageStatsManager, packageName, /*taskRootPackageName=*/ ""))
+ mContext, packageName, /*taskRootPackageName=*/ ""))
.isEqualTo(packageName);
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
index b610cfbf289..7f7fe43bb9e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
@@ -72,7 +72,7 @@ public final class DataProcessManagerTest {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- DataProcessor.sUsageStatsManager = mUsageStatsManager;
+ DatabaseUtils.sUsageStatsManager = mUsageStatsManager;
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mUserManager)
.when(mContext)
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index e2274e2d5e1..8bed054e91e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -93,7 +93,7 @@ public final class DataProcessorTest {
mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
DataProcessor.sTestSystemAppsPackageNames = Set.of();
- DataProcessor.sUsageStatsManager = mUsageStatsManager;
+ DatabaseUtils.sUsageStatsManager = mUsageStatsManager;
doReturn(mIntent).when(mContext).registerReceiver(
isA(BroadcastReceiver.class), isA(IntentFilter.class));
doReturn(100).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_SCALE), anyInt());
@@ -249,7 +249,7 @@ public final class DataProcessorTest {
final Map>>>> periodMap =
DataProcessor.generateAppUsagePeriodMap(
- 14400000L, hourlyBatteryLevelsPerDay, appUsageEventList, new ArrayList<>());
+ mContext, hourlyBatteryLevelsPerDay, appUsageEventList, new ArrayList<>());
assertThat(periodMap).hasSize(3);
// Day 1
@@ -287,7 +287,8 @@ public final class DataProcessorTest {
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
assertThat(DataProcessor.generateAppUsagePeriodMap(
- 0L, hourlyBatteryLevelsPerDay, new ArrayList<>(), new ArrayList<>())).isNull();
+ mContext, hourlyBatteryLevelsPerDay, new ArrayList<>(), new ArrayList<>()))
+ .isNull();
}
@Test
@@ -1644,7 +1645,7 @@ public final class DataProcessorTest {
final Map>> appUsagePeriodMap =
DataProcessor.buildAppUsagePeriodList(
- appUsageEvents, new ArrayList<>(), 0, 5);
+ mContext, appUsageEvents, new ArrayList<>(), 0, 5);
assertThat(appUsagePeriodMap).hasSize(2);
final Map> userMap1 = appUsagePeriodMap.get(1L);
@@ -1668,7 +1669,7 @@ public final class DataProcessorTest {
@Test
public void buildAppUsagePeriodList_emptyEventList_returnNull() {
assertThat(DataProcessor.buildAppUsagePeriodList(
- new ArrayList<>(), new ArrayList<>(), 0, 1)).isNull();
+ mContext, new ArrayList<>(), new ArrayList<>(), 0, 1)).isNull();
}
@Test
@@ -1680,7 +1681,7 @@ public final class DataProcessorTest {
AppUsageEventType.DEVICE_SHUTDOWN, /*timestamp=*/ 2));
assertThat(DataProcessor.buildAppUsagePeriodList(
- appUsageEvents, new ArrayList<>(), 0, 3)).isNull();
+ mContext, appUsageEvents, new ArrayList<>(), 0, 3)).isNull();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
index efce44e600f..24be7698375 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
@@ -16,6 +16,9 @@
package com.android.settings.fuelgauge.batteryusage;
+import static android.app.usage.UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
+import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -23,15 +26,19 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+import android.app.usage.IUsageStatsManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.MatrixCursor;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -67,6 +74,7 @@ public final class DatabaseUtilsTest {
@Mock private BatteryEntry mMockBatteryEntry2;
@Mock private BatteryEntry mMockBatteryEntry3;
@Mock private Context mMockContext;
+ @Mock private IUsageStatsManager mUsageStatsManager;
@Before
public void setUp() {
@@ -77,6 +85,7 @@ public final class DatabaseUtilsTest {
doReturn(mPackageManager).when(mMockContext).getPackageManager();
doReturn(mPackageManager).when(mContext).getPackageManager();
DatabaseUtils.getSharedPreferences(mContext).edit().clear().apply();
+ DatabaseUtils.sUsageStatsManager = mUsageStatsManager;
}
@Test
@@ -422,6 +431,71 @@ public final class DatabaseUtilsTest {
assertThat(batteryHistMap).isEmpty();
}
+ @Test
+ public void removeUsageSource_hasNoData() {
+ DatabaseUtils.removeUsageSource(mContext);
+ assertThat(
+ DatabaseUtils
+ .getSharedPreferences(mContext)
+ .contains(DatabaseUtils.KEY_LAST_USAGE_SOURCE))
+ .isFalse();
+ }
+
+ @Test
+ public void removeUsageSource_hasData_deleteUsageSource() {
+ final SharedPreferences sharedPreferences = DatabaseUtils.getSharedPreferences(mContext);
+ sharedPreferences
+ .edit()
+ .putInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE, USAGE_SOURCE_TASK_ROOT_ACTIVITY)
+ .apply();
+
+ DatabaseUtils.removeUsageSource(mContext);
+
+ assertThat(
+ DatabaseUtils
+ .getSharedPreferences(mContext)
+ .contains(DatabaseUtils.KEY_LAST_USAGE_SOURCE))
+ .isFalse();
+ }
+
+ @Test
+ public void getUsageSource_hasData() {
+ final SharedPreferences sharedPreferences = DatabaseUtils.getSharedPreferences(mContext);
+ sharedPreferences
+ .edit()
+ .putInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE, USAGE_SOURCE_TASK_ROOT_ACTIVITY)
+ .apply();
+
+ assertThat(DatabaseUtils.getUsageSource(mContext))
+ .isEqualTo(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
+ }
+
+ @Test
+ public void getUsageSource_notHasData_writeLoadedData() throws RemoteException {
+ when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
+
+ assertThat(DatabaseUtils.getUsageSource(mContext))
+ .isEqualTo(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
+ assertThat(
+ DatabaseUtils
+ .getSharedPreferences(mContext)
+ .getInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE, USAGE_SOURCE_CURRENT_ACTIVITY))
+ .isEqualTo(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
+ }
+
+ @Test
+ public void getUsageSource_throwException_writeDefaultData() throws RemoteException {
+ when(mUsageStatsManager.getUsageSource()).thenThrow(new RemoteException());
+
+ assertThat(DatabaseUtils.getUsageSource(mContext))
+ .isEqualTo(USAGE_SOURCE_CURRENT_ACTIVITY);
+ assertThat(
+ DatabaseUtils
+ .getSharedPreferences(mContext)
+ .getInt(DatabaseUtils.KEY_LAST_USAGE_SOURCE, USAGE_SOURCE_CURRENT_ACTIVITY))
+ .isEqualTo(USAGE_SOURCE_CURRENT_ACTIVITY);
+ }
+
@Test
public void recordDateTime_writeDataIntoSharedPreferences() {
final String preferenceKey = "test_preference_key";