Snap for 7206732 from d604ca93dc to sc-v2-release

Change-Id: I9c683cb36352141f441ff0c164436881190ae383
This commit is contained in:
android-build-team Robot
2021-03-14 00:08:41 +00:00
30 changed files with 838 additions and 205 deletions

View File

@@ -4013,4 +4013,36 @@
column="5"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;0&quot; android:color=&quot;#FF4285F4&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/one_handed_guideline.xml"
line="34"
column="36"/>
</issue>
<issue
id="HardCodedColor"
severity="Error"
message="Avoid using hardcoded color"
category="Correctness"
priority="4"
summary="Using hardcoded color"
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
errorLine1=" &lt;item android:offset=&quot;1&quot; android:color=&quot;#004385F5&quot;/>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="res/drawable/one_handed_guideline.xml"
line="35"
column="36"/>
</issue>
</issues>

View File

@@ -3188,6 +3188,10 @@
<string name="status_prl_version">PRL version</string>
<!-- About phone screen, title for MEID for multi-sim devices -->
<string name="meid_multi_sim">MEID (sim slot %1$d)</string>
<!-- The status text when (Wi-Fi or Bluetooth) scanning is on. [CHAR LIMIT=100] -->
<string name="scanning_status_text_on">On</string>
<!-- The status text when (Wi-Fi or Bluetooth) scanning is off. [CHAR LIMIT=100] -->
<string name="scanning_status_text_off">Off</string>
<!-- The status text when both Wi-Fi scanning and Bluetooth scanning are on. [CHAR LIMIT=100] -->
<string name="scanning_status_text_wifi_on_ble_on">Both Wi\u2011Fi and Bluetooth scanning are on</string>
<!-- The status text when Wi-Fi scanning is on and Bluetooth scanning are off. [CHAR LIMIT=100] -->

View File

@@ -18,21 +18,21 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/location_services_screen_title">
<SwitchPreference
android:title="@string/location_scanning_wifi_always_scanning_title"
android:summary="@string/location_scanning_wifi_always_scanning_description"
android:defaultValue="true"
android:key="wifi_always_scanning" />
<SwitchPreference
android:title="@string/location_scanning_bluetooth_always_scanning_title"
android:summary="@string/location_scanning_bluetooth_always_scanning_description"
android:defaultValue="true"
android:key="bluetooth_always_scanning" />
<PreferenceCategory
android:key="location_services"
android:layout="@layout/preference_category_no_label"
settings:controller="com.android.settings.location.LocationInjectedServicesPreferenceController"/>
<Preference
android:fragment="com.android.settings.location.WifiScanningFragment"
android:key="location_services_wifi_scanning"
android:title="@string/location_scanning_wifi_always_scanning_title"
settings:controller="com.android.settings.location.LocationServicesWifiScanningPreferenceController"/>
<Preference
android:fragment="com.android.settings.location.BluetoothScanningFragment"
android:key="location_services_bluetooth_scanning"
android:title="@string/location_scanning_bluetooth_always_scanning_title"
settings:controller="com.android.settings.location.LocationServicesBluetoothScanningPreferenceController"/>
</PreferenceScreen>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/location_scanning_bluetooth_always_scanning_title">
<com.android.settingslib.widget.MainSwitchPreference
android:key="bluetooth_always_scanning_switch"
android:title="@string/location_scanning_bluetooth_always_scanning_title"
settings:controller="com.android.settings.location.BluetoothScanningMainSwitchPreferenceController"/>
<com.android.settingslib.widget.FooterPreference
android:key="bluetooth_always_scanning_footer"
android:title="@string/location_scanning_bluetooth_always_scanning_description"
android:selectable="false"
settings:searchable="false"/>
</PreferenceScreen>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/location_scanning_wifi_always_scanning_title">
<com.android.settingslib.widget.MainSwitchPreference
android:key="wifi_always_scanning_switch"
android:title="@string/location_scanning_wifi_always_scanning_title"
settings:controller="com.android.settings.location.WifiScanningMainSwitchPreferenceController"/>
<com.android.settingslib.widget.FooterPreference
android:key="wifi_always_scanning_footer"
android:title="@string/location_scanning_wifi_always_scanning_description"
android:selectable="false"
settings:searchable="false"/>
</PreferenceScreen>

View File

@@ -230,7 +230,7 @@ public class AppBatteryPreferenceController extends BasePreferenceController
@Override
@NonNull
public Loader<BatteryUsageStats> onCreateLoader(int id, Bundle args) {
return new BatteryUsageStatsLoader(mContext);
return new BatteryUsageStatsLoader(mContext, /* includeBatteryHistory */ false);
}
@Override

View File

@@ -17,15 +17,16 @@
package com.android.settings.fuelgauge;
import android.content.Context;
import android.os.BatteryUsageStats;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
import com.android.settings.widget.UsageView;
@@ -50,11 +51,11 @@ public class BatteryHistoryPreference extends Preference {
setSelectable(false);
}
public void setStats(BatteryStatsHelper batteryStats) {
void setBatteryUsageStats(@NonNull BatteryUsageStats batteryUsageStats) {
BatteryInfo.getBatteryInfo(getContext(), info -> {
mBatteryInfo = info;
notifyChanged();
}, batteryStats, false);
}, batteryUsageStats, false);
}
public void setBottomSummary(CharSequence text) {

View File

@@ -20,16 +20,18 @@ import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryStats.HistoryItem;
import android.os.Bundle;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
import android.os.SystemClock;
import android.text.format.Formatter;
import android.util.SparseIntArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.settings.Utils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.UsageView;
@@ -52,7 +54,7 @@ public class BatteryInfo {
public String statusLabel;
public String suggestionLabel;
private boolean mCharging;
private BatteryStats mStats;
private BatteryUsageStats mBatteryUsageStats;
private static final String LOG_TAG = "BatteryInfo";
private long timePeriod;
@@ -126,7 +128,7 @@ public class BatteryInfo {
parserList[i] = parsers[i];
}
parserList[parsers.length] = parser;
parse(mStats, parserList);
parseBatteryHistory(parserList);
String timeString = context.getString(R.string.charge_length_format,
Formatter.formatShortElapsedTime(context, timePeriod));
String remaining = "";
@@ -137,22 +139,25 @@ public class BatteryInfo {
view.setBottomLabels(new CharSequence[]{timeString, remaining});
}
public static void getBatteryInfo(final Context context, final Callback callback) {
BatteryInfo.getBatteryInfo(context, callback, null /* statsHelper */,
false /* shortString */);
}
public static void getBatteryInfo(final Context context, final Callback callback,
boolean shortString) {
BatteryInfo.getBatteryInfo(context, callback, null /* statsHelper */, shortString);
BatteryInfo.getBatteryInfo(context, callback, /* batteryUsageStats */ null, shortString);
}
public static void getBatteryInfo(final Context context, final Callback callback,
final BatteryStatsHelper statsHelper, boolean shortString) {
@Nullable final BatteryUsageStats batteryUsageStats,
boolean shortString) {
new AsyncTask<Void, Void, BatteryInfo>() {
@Override
protected BatteryInfo doInBackground(Void... params) {
return getBatteryInfo(context, statsHelper, shortString);
BatteryUsageStats stats;
if (batteryUsageStats != null) {
stats = batteryUsageStats;
} else {
stats = context.getSystemService(BatteryStatsManager.class)
.getBatteryUsageStats();
}
return getBatteryInfo(context, stats, shortString);
}
@Override
@@ -164,18 +169,13 @@ public class BatteryInfo {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
/**
* Creates a BatteryInfo based on BatteryUsageStats
*/
@WorkerThread
public static BatteryInfo getBatteryInfo(final Context context,
final BatteryStatsHelper statsHelper, boolean shortString) {
final BatteryStats stats;
@NonNull final BatteryUsageStats batteryUsageStats, boolean shortString) {
final long batteryStatsTime = System.currentTimeMillis();
if (statsHelper == null) {
final BatteryStatsHelper localStatsHelper = new BatteryStatsHelper(context,
true);
localStatsHelper.create((Bundle) null);
stats = localStatsHelper.getStats();
} else {
stats = statsHelper.getStats();
}
BatteryUtils.logRuntime(LOG_TAG, "time for getStats", batteryStatsTime);
final long startTime = System.currentTimeMillis();
@@ -197,38 +197,38 @@ public class BatteryInfo {
Estimate.storeCachedEstimate(context, estimate);
BatteryUtils
.logRuntime(LOG_TAG, "time for enhanced BatteryInfo", startTime);
return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
return BatteryInfo.getBatteryInfo(context, batteryBroadcast, batteryUsageStats,
estimate, elapsedRealtimeUs, shortString);
}
}
final long prediction = discharging
? stats.computeBatteryTimeRemaining(elapsedRealtimeUs) : 0;
final long prediction = discharging ? batteryUsageStats.getBatteryTimeRemainingMs() : 0;
final Estimate estimate = new Estimate(
PowerUtil.convertUsToMs(prediction),
false, /* isBasedOnUsage */
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
BatteryUtils.logRuntime(LOG_TAG, "time for regular BatteryInfo", startTime);
return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
return BatteryInfo.getBatteryInfo(context, batteryBroadcast, batteryUsageStats,
estimate, elapsedRealtimeUs, shortString);
}
@WorkerThread
public static BatteryInfo getBatteryInfoOld(Context context, Intent batteryBroadcast,
BatteryStats stats, long elapsedRealtimeUs, boolean shortString) {
BatteryUsageStats batteryUsageStats, long elapsedRealtimeUs, boolean shortString) {
Estimate estimate = new Estimate(
PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)),
batteryUsageStats.getBatteryTimeRemainingMs(),
false,
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
return getBatteryInfo(context, batteryBroadcast, stats, estimate, elapsedRealtimeUs,
shortString);
return getBatteryInfo(context, batteryBroadcast, batteryUsageStats, estimate,
elapsedRealtimeUs, shortString);
}
@WorkerThread
public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
BatteryStats stats, Estimate estimate, long elapsedRealtimeUs, boolean shortString) {
@NonNull BatteryUsageStats batteryUsageStats, Estimate estimate,
long elapsedRealtimeUs, boolean shortString) {
final long startTime = System.currentTimeMillis();
BatteryInfo info = new BatteryInfo();
info.mStats = stats;
info.mBatteryUsageStats = batteryUsageStats;
info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
info.batteryPercentString = Utils.formatPercentage(info.batteryLevel);
info.mCharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
@@ -241,16 +241,17 @@ public class BatteryInfo {
if (!info.mCharging) {
updateBatteryInfoDischarging(context, shortString, estimate, info);
} else {
updateBatteryInfoCharging(context, batteryBroadcast, stats, elapsedRealtimeUs, info);
updateBatteryInfoCharging(context, batteryBroadcast, batteryUsageStats,
info);
}
BatteryUtils.logRuntime(LOG_TAG, "time for getBatteryInfo", startTime);
return info;
}
private static void updateBatteryInfoCharging(Context context, Intent batteryBroadcast,
BatteryStats stats, long elapsedRealtimeUs, BatteryInfo info) {
BatteryUsageStats stats, BatteryInfo info) {
final Resources resources = context.getResources();
final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
final long chargeTimeMs = stats.getChargeTimeRemainingMs();
final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
info.discharging = false;
@@ -260,8 +261,8 @@ public class BatteryInfo {
int chargingLimitedResId = R.string.power_charging_limited;
info.chargeLabel =
context.getString(chargingLimitedResId, info.batteryPercentString);
} else if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
info.remainingTimeUs = chargeTime;
} else if (chargeTimeMs > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
info.remainingTimeUs = PowerUtil.convertMsToUs(chargeTimeMs);
CharSequence timeString = StringUtil.formatElapsedTime(context,
PowerUtil.convertUsToMs(info.remainingTimeUs), false /* withSeconds */);
int resId = R.string.power_charging_duration;
@@ -313,7 +314,11 @@ public class BatteryInfo {
void onParsingDone();
}
public static void parse(BatteryStats stats, BatteryDataParser... parsers) {
/**
* Iterates over battery history included in the BatteryUsageStats that this object
* was initialized with.
*/
public void parseBatteryHistory(BatteryDataParser... parsers) {
long startWalltime = 0;
long endWalltime = 0;
long historyStart = 0;
@@ -324,41 +329,41 @@ public class BatteryInfo {
int lastInteresting = 0;
int pos = 0;
boolean first = true;
if (stats.startIteratingHistoryLocked()) {
final HistoryItem rec = new HistoryItem();
while (stats.getNextHistoryLocked(rec)) {
pos++;
if (first) {
first = false;
historyStart = rec.time;
final BatteryStatsHistoryIterator iterator1 =
mBatteryUsageStats.iterateBatteryStatsHistory();
final HistoryItem rec = new HistoryItem();
while (iterator1.next(rec)) {
pos++;
if (first) {
first = false;
historyStart = rec.time;
}
if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
|| rec.cmd == HistoryItem.CMD_RESET) {
// If there is a ridiculously large jump in time, then we won't be
// able to create a good chart with that data, so just ignore the
// times we got before and pretend like our data extends back from
// the time we have now.
// Also, if we are getting a time change and we are less than 5 minutes
// since the start of the history real time, then also use this new
// time to compute the base time, since whatever time we had before is
// pretty much just noise.
if (rec.currentTime > (lastWallTime + (180 * 24 * 60 * 60 * 1000L))
|| rec.time < (historyStart + (5 * 60 * 1000L))) {
startWalltime = 0;
}
if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
|| rec.cmd == HistoryItem.CMD_RESET) {
// If there is a ridiculously large jump in time, then we won't be
// able to create a good chart with that data, so just ignore the
// times we got before and pretend like our data extends back from
// the time we have now.
// Also, if we are getting a time change and we are less than 5 minutes
// since the start of the history real time, then also use this new
// time to compute the base time, since whatever time we had before is
// pretty much just noise.
if (rec.currentTime > (lastWallTime + (180 * 24 * 60 * 60 * 1000L))
|| rec.time < (historyStart + (5 * 60 * 1000L))) {
startWalltime = 0;
}
lastWallTime = rec.currentTime;
lastRealtime = rec.time;
if (startWalltime == 0) {
startWalltime = lastWallTime - (lastRealtime - historyStart);
}
}
if (rec.isDeltaData()) {
lastInteresting = pos;
historyEnd = rec.time;
lastWallTime = rec.currentTime;
lastRealtime = rec.time;
if (startWalltime == 0) {
startWalltime = lastWallTime - (lastRealtime - historyStart);
}
}
if (rec.isDeltaData()) {
lastInteresting = pos;
historyEnd = rec.time;
}
}
stats.finishIteratingHistoryLocked();
endWalltime = lastWallTime + historyEnd - lastRealtime;
int i = 0;
@@ -367,9 +372,11 @@ public class BatteryInfo {
for (int j = 0; j < parsers.length; j++) {
parsers[j].onParsingStarted(startWalltime, endWalltime);
}
if (endWalltime > startWalltime && stats.startIteratingHistoryLocked()) {
final HistoryItem rec = new HistoryItem();
while (stats.getNextHistoryLocked(rec) && i < N) {
if (endWalltime > startWalltime) {
final BatteryStatsHistoryIterator iterator2 =
mBatteryUsageStats.iterateBatteryStatsHistory();
while (iterator2.next(rec) && i < N) {
if (rec.isDeltaData()) {
curWalltime += rec.time - lastRealtime;
lastRealtime = rec.time;
@@ -404,8 +411,6 @@ public class BatteryInfo {
}
}
stats.finishIteratingHistoryLocked();
for (int j = 0; j < parsers.length; j++) {
parsers[j].onParsingDone();
}

View File

@@ -19,7 +19,6 @@ import android.content.Context;
import androidx.annotation.VisibleForTesting;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settingslib.utils.AsyncLoaderCompat;
/**
@@ -28,17 +27,14 @@ import com.android.settingslib.utils.AsyncLoaderCompat;
* when not available.
*/
public class BatteryInfoLoader extends AsyncLoaderCompat<BatteryInfo>{
BatteryStatsHelper mStatsHelper;
private static final String LOG_TAG = "BatteryInfoLoader";
@VisibleForTesting
BatteryUtils batteryUtils;
BatteryUtils mBatteryUtils;
public BatteryInfoLoader(Context context, BatteryStatsHelper batteryStatsHelper) {
public BatteryInfoLoader(Context context) {
super(context);
mStatsHelper = batteryStatsHelper;
batteryUtils = BatteryUtils.getInstance(context);
mBatteryUtils = BatteryUtils.getInstance(context);
}
@Override
@@ -48,6 +44,6 @@ public class BatteryInfoLoader extends AsyncLoaderCompat<BatteryInfo>{
@Override
public BatteryInfo loadInBackground() {
return batteryUtils.getBatteryInfo(mStatsHelper, LOG_TAG);
return mBatteryUtils.getBatteryInfo(LOG_TAG);
}
}

View File

@@ -19,6 +19,7 @@ package com.android.settings.fuelgauge;
import android.content.Context;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import com.android.settingslib.utils.AsyncLoaderCompat;
@@ -27,15 +28,21 @@ import com.android.settingslib.utils.AsyncLoaderCompat;
*/
public class BatteryUsageStatsLoader extends AsyncLoaderCompat<BatteryUsageStats> {
private final BatteryStatsManager mBatteryStatsManager;
private final boolean mIncludeBatteryHistory;
public BatteryUsageStatsLoader(Context context) {
public BatteryUsageStatsLoader(Context context, boolean includeBatteryHistory) {
super(context);
mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class);
mIncludeBatteryHistory = includeBatteryHistory;
}
@Override
public BatteryUsageStats loadInBackground() {
return mBatteryStatsManager.getBatteryUsageStats();
final BatteryUsageStatsQuery.Builder builder = new BatteryUsageStatsQuery.Builder();
if (mIncludeBatteryHistory) {
builder.includeBatteryHistory();
}
return mBatteryStatsManager.getBatteryUsageStats(builder.build());
}
@Override

View File

@@ -24,6 +24,9 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.BatteryStats;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
@@ -103,7 +106,7 @@ public class BatteryUtils {
}
@VisibleForTesting
BatteryUtils(Context context) {
public BatteryUtils(Context context) {
mContext = context;
mPackageManager = context.getPackageManager();
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
@@ -472,29 +475,35 @@ public class BatteryUtils {
}
@WorkerThread
public BatteryInfo getBatteryInfo(final BatteryStatsHelper statsHelper, final String tag) {
public BatteryInfo getBatteryInfo(final String tag) {
final BatteryStatsManager systemService = mContext.getSystemService(
BatteryStatsManager.class);
final BatteryUsageStats batteryUsageStats = systemService.getBatteryUsageStats(
new BatteryUsageStatsQuery.Builder().includeBatteryHistory().build());
final long startTime = System.currentTimeMillis();
// Stuff we always need to get BatteryInfo
final Intent batteryBroadcast = mContext.registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
final long elapsedRealtimeUs = PowerUtil.convertMsToUs(
SystemClock.elapsedRealtime());
final BatteryStats stats = statsHelper.getStats();
BatteryInfo batteryInfo;
Estimate estimate = getEnhancedEstimate();
// couldn't get estimate from cache or provider, use fallback
if (estimate == null) {
estimate = new Estimate(
PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)),
PowerUtil.convertUsToMs(batteryUsageStats.getBatteryTimeRemainingMs()),
false /* isBasedOnUsage */,
EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
}
BatteryUtils.logRuntime(tag, "BatteryInfoLoader post query", startTime);
batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast, stats,
estimate, elapsedRealtimeUs, false /* shortString */);
batteryInfo = BatteryInfo.getBatteryInfo(mContext, batteryBroadcast,
batteryUsageStats, estimate, elapsedRealtimeUs, false /* shortString */);
BatteryUtils.logRuntime(tag, "BatteryInfoLoader.loadInBackground", startTime);
return batteryInfo;

View File

@@ -19,6 +19,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryStats;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
import android.os.SystemClock;
import com.android.internal.os.BatteryStatsHelper;
@@ -56,15 +58,17 @@ public class DebugEstimatesLoader extends AsyncLoaderCompat<List<BatteryInfo>> {
Intent batteryBroadcast = getContext().registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
BatteryStats stats = mStatsHelper.getStats();
BatteryUsageStats batteryUsageStats =
context.getSystemService(BatteryStatsManager.class).getBatteryUsageStats();
BatteryInfo oldinfo = BatteryInfo.getBatteryInfoOld(getContext(), batteryBroadcast,
stats, elapsedRealtimeUs, false);
batteryUsageStats, elapsedRealtimeUs, false);
Estimate estimate = powerUsageFeatureProvider.getEnhancedBatteryPrediction(context);
if (estimate == null) {
estimate = new Estimate(0, false, EstimateKt.AVERAGE_TIME_TO_DISCHARGE_UNKNOWN);
}
BatteryInfo newInfo = BatteryInfo.getBatteryInfo(getContext(), batteryBroadcast, stats,
BatteryInfo newInfo = BatteryInfo.getBatteryInfo(getContext(), batteryBroadcast,
batteryUsageStats,
estimate, elapsedRealtimeUs, false);
List<BatteryInfo> infos = new ArrayList<>();

View File

@@ -141,6 +141,11 @@ public class PowerUsageAdvanced extends PowerUsageBase {
return controllers;
}
@Override
protected boolean isBatteryHistoryNeeded() {
return true;
}
@Override
protected void refreshUi(@BatteryUpdateType int refreshType) {
final Context context = getContext();

View File

@@ -19,10 +19,12 @@ import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpd
import android.app.Activity;
import android.content.Context;
import android.os.BatteryUsageStats;
import android.os.Bundle;
import android.os.UserManager;
import android.view.Menu;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
@@ -40,12 +42,29 @@ public abstract class PowerUsageBase extends DashboardFragment {
static final int MENU_STATS_REFRESH = Menu.FIRST + 1;
private static final String TAG = "PowerUsageBase";
private static final String KEY_REFRESH_TYPE = "refresh_type";
private static final String KEY_INCLUDE_HISTORY = "include_history";
private static final int LOADER_BATTERY_STATS_HELPER = 0;
private static final int LOADER_BATTERY_USAGE_STATS = 1;
protected BatteryStatsHelper mStatsHelper;
@VisibleForTesting
BatteryUsageStats mBatteryUsageStats;
protected UserManager mUm;
private BatteryBroadcastReceiver mBatteryBroadcastReceiver;
protected boolean mIsBatteryPresent = true;
// TODO(b/180630447): switch to BatteryUsageStatsLoader and remove all references to
// BatteryStatsHelper and BatterySipper
@VisibleForTesting
final BatteryStatsHelperLoaderCallbacks mBatteryStatsHelperLoaderCallbacks =
new BatteryStatsHelperLoaderCallbacks();
@VisibleForTesting
final BatteryUsageStatsLoaderCallbacks mBatteryUsageStatsLoaderCallbacks =
new BatteryUsageStatsLoaderCallbacks();
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
@@ -83,42 +102,73 @@ public abstract class PowerUsageBase extends DashboardFragment {
protected void restartBatteryStatsLoader(int refreshType) {
final Bundle bundle = new Bundle();
bundle.putInt(KEY_REFRESH_TYPE, refreshType);
bundle.putBoolean(KEY_INCLUDE_HISTORY, isBatteryHistoryNeeded());
getLoaderManager().restartLoader(LOADER_BATTERY_STATS_HELPER, bundle,
mBatteryStatsHelperLoaderCallbacks);
getLoaderManager().restartLoader(LOADER_BATTERY_USAGE_STATS, bundle,
mBatteryUsageStatsLoaderCallbacks);
}
getLoaderManager().restartLoader(0, bundle, new PowerLoaderCallback());
private void onLoadFinished(@BatteryUpdateType int refreshType) {
// Wait for both loaders to finish before proceeding.
if (mStatsHelper == null || mBatteryUsageStats == null) {
return;
}
refreshUi(refreshType);
}
protected abstract void refreshUi(@BatteryUpdateType int refreshType);
protected abstract boolean isBatteryHistoryNeeded();
protected void updatePreference(BatteryHistoryPreference historyPref) {
final long startTime = System.currentTimeMillis();
historyPref.setStats(mStatsHelper);
historyPref.setBatteryUsageStats(mBatteryUsageStats);
BatteryUtils.logRuntime(TAG, "updatePreference", startTime);
}
/**
* {@link android.app.LoaderManager.LoaderCallbacks} for {@link PowerUsageBase} to load
* the {@link BatteryStatsHelper}
*/
public class PowerLoaderCallback implements LoaderManager.LoaderCallbacks<BatteryStatsHelper> {
private class BatteryStatsHelperLoaderCallbacks
implements LoaderManager.LoaderCallbacks<BatteryStatsHelper> {
private int mRefreshType;
@Override
public Loader<BatteryStatsHelper> onCreateLoader(int id,
Bundle args) {
public Loader<BatteryStatsHelper> onCreateLoader(int id, Bundle args) {
mRefreshType = args.getInt(KEY_REFRESH_TYPE);
return new BatteryStatsHelperLoader(getContext());
}
@Override
public void onLoadFinished(Loader<BatteryStatsHelper> loader,
BatteryStatsHelper statsHelper) {
mStatsHelper = statsHelper;
refreshUi(mRefreshType);
BatteryStatsHelper batteryHelper) {
mStatsHelper = batteryHelper;
PowerUsageBase.this.onLoadFinished(mRefreshType);
}
@Override
public void onLoaderReset(Loader<BatteryStatsHelper> loader) {
}
}
private class BatteryUsageStatsLoaderCallbacks
implements LoaderManager.LoaderCallbacks<BatteryUsageStats> {
private int mRefreshType;
@Override
@NonNull
public Loader<BatteryUsageStats> onCreateLoader(int id, Bundle args) {
mRefreshType = args.getInt(KEY_REFRESH_TYPE);
return new BatteryUsageStatsLoader(getContext(), args.getBoolean(KEY_INCLUDE_HISTORY));
}
@Override
public void onLoadFinished(Loader<BatteryUsageStats> loader,
BatteryUsageStats batteryUsageStats) {
mBatteryUsageStats = batteryUsageStats;
PowerUsageBase.this.onLoadFinished(mRefreshType);
}
@Override
public void onLoaderReset(Loader<BatteryUsageStats> loader) {
}
}
}

View File

@@ -88,7 +88,7 @@ public class PowerUsageSummary extends PowerUsageBase implements
@Override
public Loader<BatteryInfo> onCreateLoader(int i, Bundle bundle) {
return new BatteryInfoLoader(getContext(), mStatsHelper);
return new BatteryInfoLoader(getContext());
}
@Override
@@ -190,6 +190,11 @@ public class PowerUsageSummary extends PowerUsageBase implements
return R.string.help_url_battery;
}
@Override
protected boolean isBatteryHistoryNeeded() {
return false;
}
protected void refreshUi(@BatteryUpdateType int refreshType) {
final Context context = getContext();
if (context == null) {

View File

@@ -65,12 +65,11 @@ public class BatteryTipLoader extends AsyncLoaderCompat<List<BatteryTip>> {
}
final List<BatteryTip> tips = new ArrayList<>();
final BatteryTipPolicy policy = new BatteryTipPolicy(getContext());
final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(mBatteryStatsHelper, TAG);
final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(TAG);
final Context context = getContext();
tips.add(new LowBatteryDetector(context, policy, batteryInfo).detect());
tips.add(new HighUsageDetector(context, policy, mBatteryStatsHelper,
batteryInfo.discharging).detect());
tips.add(new HighUsageDetector(context, policy, mBatteryStatsHelper, batteryInfo).detect());
tips.add(new SmartBatteryDetector(policy, context.getContentResolver()).detect());
tips.add(new EarlyWarningDetector(policy, context).detect());
tips.add(new BatteryDefenderDetector(batteryInfo).detect());

View File

@@ -45,6 +45,7 @@ import java.util.concurrent.TimeUnit;
public class HighUsageDetector implements BatteryTipDetector {
private BatteryTipPolicy mPolicy;
private BatteryStatsHelper mBatteryStatsHelper;
private final BatteryInfo mBatteryInfo;
private List<AppInfo> mHighUsageAppList;
@VisibleForTesting
HighUsageDataParser mDataParser;
@@ -54,14 +55,15 @@ public class HighUsageDetector implements BatteryTipDetector {
boolean mDischarging;
public HighUsageDetector(Context context, BatteryTipPolicy policy,
BatteryStatsHelper batteryStatsHelper, boolean discharging) {
BatteryStatsHelper batteryStatsHelper, BatteryInfo batteryInfo) {
mPolicy = policy;
mBatteryStatsHelper = batteryStatsHelper;
mBatteryInfo = batteryInfo;
mHighUsageAppList = new ArrayList<>();
mBatteryUtils = BatteryUtils.getInstance(context);
mDataParser = new HighUsageDataParser(mPolicy.highUsagePeriodMs,
mPolicy.highUsageBatteryDraining);
mDischarging = discharging;
mDischarging = batteryInfo.discharging;
}
@Override
@@ -115,6 +117,6 @@ public class HighUsageDetector implements BatteryTipDetector {
@VisibleForTesting
void parseBatteryData() {
BatteryInfo.parse(mBatteryStatsHelper.getStats(), mDataParser);
mBatteryInfo.parseBatteryHistory(mDataParser);
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.location;
import android.app.settings.SettingsEnums;
import android.content.Context;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
/**
* A page that configures the Bluetooth scanning setting.
*/
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class BluetoothScanningFragment extends DashboardFragment {
private static final String TAG = "BluetoothScanningFragment";
@Override
public int getMetricsCategory() {
return SettingsEnums.LOCATION_SERVICES;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.location_services_bluetooth_scanning;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new BluetoothScanningPreferenceController(context));
return controllers;
}
/**
* For Search.
*/
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.location_services_bluetooth_scanning) {
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context
context) {
return buildPreferenceControllers(context);
}
};
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 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.location;
import android.content.Context;
import android.provider.Settings;
import android.widget.Switch;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.widget.MainSwitchPreference;
import com.android.settingslib.widget.OnMainSwitchChangeListener;
/**
* Preference controller for Bluetooth scanning main switch.
*/
public class BluetoothScanningMainSwitchPreferenceController extends TogglePreferenceController
implements OnMainSwitchChangeListener {
private static final String KEY_BLUETOOTH_SCANNING_SWITCH = "bluetooth_always_scanning_switch";
public BluetoothScanningMainSwitchPreferenceController(Context context) {
super(context, KEY_BLUETOOTH_SCANNING_SWITCH);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
MainSwitchPreference pref = screen.findPreference(getPreferenceKey());
pref.addOnSwitchChangeListener(this);
pref.updateStatus(isChecked());
}
@Override
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_location_scanning)
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isChecked() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
}
@Override
public boolean setChecked(boolean isChecked) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, isChecked ? 1 : 0);
// Returning true means the underlying setting is updated.
return true;
}
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
if (isChecked != isChecked()) {
setChecked(isChecked);
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 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.location;
import android.content.Context;
import android.provider.Settings;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
/**
* Preference controller for Bluetooth scanning in Location Services.
*/
public class LocationServicesBluetoothScanningPreferenceController extends
BasePreferenceController {
public LocationServicesBluetoothScanningPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public CharSequence getSummary() {
final boolean bleScanOn = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1;
int resId =
bleScanOn ? R.string.scanning_status_text_on : R.string.scanning_status_text_off;
return mContext.getString(resId);
}
@AvailabilityStatus
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_location_scanning)
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 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.location;
import android.content.Context;
import android.net.wifi.WifiManager;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
/**
* Preference controller for Wi-Fi scanning in Location Services.
*/
public class LocationServicesWifiScanningPreferenceController extends BasePreferenceController {
private final WifiManager mWifiManager;
public LocationServicesWifiScanningPreferenceController(Context context, String key) {
super(context, key);
mWifiManager = context.getSystemService(WifiManager.class);
}
@Override
public CharSequence getSummary() {
final boolean wifiScanOn = mWifiManager.isScanAlwaysAvailable();
int resId =
wifiScanOn ? R.string.scanning_status_text_on : R.string.scanning_status_text_off;
return mContext.getString(resId);
}
@AvailabilityStatus
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_location_scanning)
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.location;
import android.app.settings.SettingsEnums;
import android.content.Context;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
/**
* A page that configures the Wi-Fi scanning setting.
*/
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class WifiScanningFragment extends DashboardFragment {
private static final String TAG = "WifiScanningFragment";
@Override
public int getMetricsCategory() {
return SettingsEnums.LOCATION_SERVICES;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.location_services_wifi_scanning;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new WifiScanningPreferenceController(context));
return controllers;
}
/**
* For Search.
*/
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.location_services_wifi_scanning) {
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context
context) {
return buildPreferenceControllers(context);
}
};
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright 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.location;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.widget.Switch;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.widget.MainSwitchPreference;
import com.android.settingslib.widget.OnMainSwitchChangeListener;
/**
* Preference controller for Wi-Fi scanning main switch.
*/
public class WifiScanningMainSwitchPreferenceController extends TogglePreferenceController
implements OnMainSwitchChangeListener {
private static final String KEY_WIFI_SCANNING_SWITCH = "wifi_always_scanning_switch";
private final WifiManager mWifiManager;
public WifiScanningMainSwitchPreferenceController(Context context) {
super(context, KEY_WIFI_SCANNING_SWITCH);
mWifiManager = context.getSystemService(WifiManager.class);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
MainSwitchPreference pref = screen.findPreference(getPreferenceKey());
pref.addOnSwitchChangeListener(this);
pref.updateStatus(isChecked());
}
@Override
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_location_scanning)
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isChecked() {
return mWifiManager.isScanAlwaysAvailable();
}
@Override
public boolean setChecked(boolean isChecked) {
mWifiManager.setScanAlwaysAvailable(isChecked);
// Returning true means the underlying setting is updated.
return true;
}
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
if (isChecked != isChecked()) {
setChecked(isChecked);
}
}
}

View File

@@ -127,20 +127,23 @@ public class ConfigureNotificationSettings extends DashboardFragment implements
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final PreferenceScreen screen = getPreferenceScreen();
final Bundle arguments = getArguments();
// TODO(b/182237530): This method should be removed when this flag is deprecated.
if (!FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.SILKY_HOME)) {
final PreferenceScreen screen = getPreferenceScreen();
final Bundle arguments = getArguments();
if (screen == null) {
return;
}
if (arguments != null) {
final String highlightKey = arguments.getString(EXTRA_FRAGMENT_ARG_KEY);
if (!TextUtils.isEmpty(highlightKey)) {
final PreferenceCategory advancedCategory =
screen.findPreference(KEY_ADVANCED_CATEGORY);
// Has highlight row - expand everything
advancedCategory.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
scrollToPreference(advancedCategory);
if (screen == null) {
return;
}
if (arguments != null) {
final String highlightKey = arguments.getString(EXTRA_FRAGMENT_ARG_KEY);
if (!TextUtils.isEmpty(highlightKey)) {
final PreferenceCategory advancedCategory =
screen.findPreference(KEY_ADVANCED_CATEGORY);
// Has highlight row - expand everything
advancedCategory.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
scrollToPreference(advancedCategory);
}
}
}
}

View File

@@ -19,23 +19,23 @@ package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
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.Intent;
import android.os.BatteryStats;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.testutils.BatteryTestUtils;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -46,10 +46,10 @@ public class BatteryInfoLoaderTest {
private static final long TEST_TIME_REMAINING = 1000L;
@Mock (answer = Answers.RETURNS_DEEP_STUBS)
private BatteryStatsHelper mHelper;
@Mock (answer = Answers.RETURNS_DEEP_STUBS)
private BatteryStats mStats;
@Mock
private BatteryStatsManager mBatteryStatsManager;
@Mock
private BatteryUsageStats mBatteryUsageStats;
private Context mContext;
@@ -60,8 +60,11 @@ public class BatteryInfoLoaderTest {
FakeFeatureFactory.setupForTest().getPowerUsageFeatureProvider(mContext);
doReturn(mContext).when(mContext).getApplicationContext();
when(mStats.computeBatteryTimeRemaining(anyLong())).thenReturn(TEST_TIME_REMAINING);
doReturn(mStats).when(mHelper).getStats();
when(mContext.getSystemService(eq(Context.BATTERY_STATS_SERVICE)))
.thenReturn(mBatteryStatsManager);
when(mBatteryUsageStats.getBatteryTimeRemainingMs()).thenReturn(TEST_TIME_REMAINING);
when(mBatteryStatsManager.getBatteryUsageStats(any(BatteryUsageStatsQuery.class)))
.thenReturn(mBatteryUsageStats);
final Intent dischargingBatteryBroadcast = BatteryTestUtils.getDischargingIntent();
doReturn(dischargingBatteryBroadcast).when(mContext).registerReceiver(any(), any());
@@ -69,8 +72,8 @@ public class BatteryInfoLoaderTest {
@Test
public void test_loadInBackground_dischargingOldEstimate_dischargingLabelNotNull() {
BatteryInfoLoader loader = new BatteryInfoLoader(mContext, mHelper);
loader.batteryUtils = new BatteryUtils(mContext);
BatteryInfoLoader loader = new BatteryInfoLoader(mContext);
loader.mBatteryUtils = new BatteryUtils(mContext);
BatteryInfo info = loader.loadInBackground();

View File

@@ -34,9 +34,11 @@ import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.SystemClock;
import android.util.SparseIntArray;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.settings.testutils.BatteryTestUtils;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.UsageView;
@@ -46,7 +48,6 @@ import com.android.settingslib.fuelgauge.Estimate;
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;
@@ -83,9 +84,8 @@ public class BatteryInfoTest {
private Intent mChargingBatteryBroadcast;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private BatteryStats mBatteryStats;
@Mock
private BatteryUsageStats mBatteryUsageStats;
@Before
public void setUp() {
@@ -100,9 +100,10 @@ public class BatteryInfoTest {
@Test
public void testGetBatteryInfo_hasStatusLabel() {
doReturn(REMAINING_TIME_NULL).when(mBatteryStats).computeBatteryTimeRemaining(anyLong());
doReturn(REMAINING_TIME_NULL).when(mBatteryUsageStats).getBatteryTimeRemainingMs();
BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext,
mDisChargingBatteryBroadcast, mBatteryStats, SystemClock.elapsedRealtime() * 1000,
mDisChargingBatteryBroadcast, mBatteryUsageStats,
SystemClock.elapsedRealtime() * 1000,
true /* shortString */);
assertThat(info.statusLabel).isEqualTo(STATUS_NOT_CHARGING);
@@ -110,28 +111,28 @@ public class BatteryInfoTest {
@Test
public void testGetBatteryInfo_doNotShowChargingMethod_hasRemainingTime() {
doReturn(REMAINING_TIME).when(mBatteryStats).computeChargeTimeRemaining(anyLong());
doReturn(REMAINING_TIME).when(mBatteryUsageStats).getChargeTimeRemainingMs();
BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext, mChargingBatteryBroadcast,
mBatteryStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */);
mBatteryUsageStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */);
assertThat(info.chargeLabel.toString()).isEqualTo(STATUS_CHARGING_TIME);
}
@Test
public void testGetBatteryInfo_doNotShowChargingMethod_noRemainingTime() {
doReturn(REMAINING_TIME_NULL).when(mBatteryStats).computeChargeTimeRemaining(anyLong());
doReturn(REMAINING_TIME_NULL).when(mBatteryUsageStats).getChargeTimeRemainingMs();
BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext, mChargingBatteryBroadcast,
mBatteryStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */);
mBatteryUsageStats, SystemClock.elapsedRealtime() * 1000, false /* shortString */);
assertThat(info.chargeLabel.toString()).isEqualTo(STATUS_CHARGING_NO_TIME);
}
@Test
public void testGetBatteryInfo_pluggedInUsingShortString_usesCorrectData() {
doReturn(TEST_CHARGE_TIME_REMAINING).when(mBatteryStats).computeChargeTimeRemaining(
anyLong());
doReturn(TEST_CHARGE_TIME_REMAINING / 1000)
.when(mBatteryUsageStats).getChargeTimeRemainingMs();
BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext, mChargingBatteryBroadcast,
mBatteryStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */);
mBatteryUsageStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */);
assertThat(info.discharging).isEqualTo(false);
assertThat(info.chargeLabel.toString()).isEqualTo("50% - 1 min until charged");
@@ -143,10 +144,10 @@ public class BatteryInfoTest {
true /* isBasedOnUsage */,
1000 /* averageDischargeTime */);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
BatteryInfo info2 = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000,
true /* shortString */);
// We only add special mention for the long string
@@ -163,10 +164,10 @@ public class BatteryInfoTest {
true /* isBasedOnUsage */,
1000 /* averageDischargeTime */);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
BatteryInfo info2 = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000,
true /* shortString */);
// These should be identical in either case
@@ -183,7 +184,7 @@ public class BatteryInfoTest {
true /* isBasedOnUsage */,
1000 /* averageDischargeTime */);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
assertThat(info.suggestionLabel).doesNotContain(BATTERY_RUN_OUT_PREFIX);
@@ -196,7 +197,7 @@ public class BatteryInfoTest {
true /* isBasedOnUsage */,
1000 /* averageDischargeTime */);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
mBatteryStats, estimate, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
// Check that strings are showing less than 15 minutes remaining regardless of exact time.
@@ -211,10 +212,10 @@ public class BatteryInfoTest {
@Test
public void testGetBatteryInfo_basedOnUsageFalse_usesDefaultString() {
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
BatteryInfo info2 = BatteryInfo.getBatteryInfo(mContext, mDisChargingBatteryBroadcast,
mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
true /* shortString */);
assertThat(info.remainingLabel.toString()).doesNotContain(ENHANCED_STRING_SUFFIX);
@@ -223,12 +224,11 @@ public class BatteryInfoTest {
@Test
public void testGetBatteryInfo_charging_usesChargeTime() {
doReturn(TEST_CHARGE_TIME_REMAINING)
.when(mBatteryStats)
.computeChargeTimeRemaining(anyLong());
doReturn(TEST_CHARGE_TIME_REMAINING / 1000)
.when(mBatteryUsageStats).getChargeTimeRemainingMs();
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
assertThat(info.remainingTimeUs).isEqualTo(TEST_CHARGE_TIME_REMAINING);
assertThat(info.remainingLabel.toString())
@@ -240,7 +240,7 @@ public class BatteryInfoTest {
mChargingBatteryBroadcast.putExtra(BatteryManager.EXTRA_LEVEL, 100);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
assertThat(info.chargeLabel).isEqualTo("100%");
@@ -249,13 +249,13 @@ public class BatteryInfoTest {
@Test
public void testGetBatteryInfo_chargingWithOverheated_updateChargeLabel() {
doReturn(TEST_CHARGE_TIME_REMAINING)
.when(mBatteryStats)
.computeChargeTimeRemaining(anyLong());
.when(mBatteryUsageStats)
.getChargeTimeRemainingMs();
mChargingBatteryBroadcast
.putExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
mBatteryStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
assertThat(info.isOverheated).isTrue();
@@ -264,28 +264,29 @@ public class BatteryInfoTest {
// Make our battery stats return a sequence of battery events.
private void mockBatteryStatsHistory() {
// Mock out new data every time start...Locked is called.
// Mock out new data every time iterateBatteryStatsHistory is called.
doAnswer(invocation -> {
doAnswer(new Answer() {
private int count = 0;
private long[] times = {1000, 1500, 2000};
private byte[] levels = {99, 98, 97};
BatteryStatsHistoryIterator iterator = mock(BatteryStatsHistoryIterator.class);
doAnswer(new Answer<Boolean>() {
private int mCount = 0;
private final long[] mTimes = {1000, 1500, 2000};
private final byte[] mLevels = {99, 98, 97};
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
if (count == times.length) {
public Boolean answer(InvocationOnMock invocation) throws Throwable {
if (mCount == mTimes.length) {
return false;
}
BatteryStats.HistoryItem record = invocation.getArgument(0);
record.cmd = BatteryStats.HistoryItem.CMD_UPDATE;
record.time = times[count];
record.batteryLevel = levels[count];
count++;
record.time = mTimes[mCount];
record.batteryLevel = mLevels[mCount];
mCount++;
return true;
}
}).when(mBatteryStats).getNextHistoryLocked(any(BatteryStats.HistoryItem.class));
return true;
}).when(mBatteryStats).startIteratingHistoryLocked();
}).when(iterator).next(any(BatteryStats.HistoryItem.class));
return iterator;
}).when(mBatteryUsageStats).iterateBatteryStatsHistory();
}
private void assertOnlyHistory(BatteryInfo info) {
@@ -337,9 +338,9 @@ public class BatteryInfoTest {
private BatteryInfo getBatteryInfo(boolean charging, boolean enhanced, boolean estimate) {
if (charging && estimate) {
doReturn(1000L).when(mBatteryStats).computeChargeTimeRemaining(anyLong());
doReturn(1000L).when(mBatteryUsageStats).getChargeTimeRemainingMs();
} else {
doReturn(0L).when(mBatteryStats).computeChargeTimeRemaining(anyLong());
doReturn(0L).when(mBatteryUsageStats).getChargeTimeRemainingMs();
}
Estimate batteryEstimate = new Estimate(
estimate ? 1000 : 0,
@@ -347,7 +348,7 @@ public class BatteryInfoTest {
1000 /* averageDischargeTime */);
BatteryInfo info = BatteryInfo.getBatteryInfo(mContext,
charging ? mChargingBatteryBroadcast : mDisChargingBatteryBroadcast,
mBatteryStats, batteryEstimate, SystemClock.elapsedRealtime() * 1000, false);
mBatteryUsageStats, batteryEstimate, SystemClock.elapsedRealtime() * 1000, false);
doReturn(enhanced).when(mFeatureFactory.powerUsageFeatureProvider)
.isEnhancedBatteryPredictionEnabled(mContext);
return info;

View File

@@ -48,6 +48,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.BatteryStats;
import android.os.BatteryStatsManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
@@ -157,6 +158,8 @@ public class BatteryUtilsTest {
private ApplicationInfo mApplicationInfo;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private BatteryStatsHelper mBatteryStatsHelper;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private BatteryStatsManager mBatteryStatsManager;
@Mock
private ApplicationInfo mHighApplicationInfo;
@Mock
@@ -228,6 +231,8 @@ public class BatteryUtilsTest {
mContext = spy(RuntimeEnvironment.application);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
doReturn(mBatteryStatsManager).when(mContext)
.getSystemService(Context.BATTERY_STATS_SERVICE);
mBatteryUtils = spy(new BatteryUtils(mContext));
mBatteryUtils.mPowerUsageFeatureProvider = mProvider;
doReturn(0L).when(mBatteryUtils)
@@ -741,7 +746,7 @@ public class BatteryUtilsTest {
any(IntentFilter.class))).thenReturn(new Intent());
//Should not crash
assertThat(mBatteryUtils.getBatteryInfo(mBatteryStatsHelper, TAG)).isNotNull();
assertThat(mBatteryUtils.getBatteryInfo(TAG)).isNotNull();
}
@Test

View File

@@ -74,6 +74,11 @@ public class PowerUsageBaseTest {
return 0;
}
@Override
protected boolean isBatteryHistoryNeeded() {
return false;
}
@Override
protected void refreshUi(int refreshType) {
// Do nothing

View File

@@ -77,7 +77,7 @@ public class BatteryTipLoaderTest {
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mPowerManager).when(mContext).getSystemService(Context.POWER_SERVICE);
doReturn(mIntent).when(mContext).registerReceiver(any(), any());
doReturn(mBatteryInfo).when(mBatteryUtils).getBatteryInfo(any(), any());
doReturn(mBatteryInfo).when(mBatteryUtils).getBatteryInfo(any());
mBatteryTipLoader = new BatteryTipLoader(mContext, mBatteryStatsHelper);
mBatteryTipLoader.mBatteryUtils = mBatteryUtils;
}

View File

@@ -18,7 +18,9 @@ package com.android.settings.fuelgauge.batterytip.detectors;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -26,8 +28,11 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryStats;
import android.text.format.DateUtils;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
@@ -53,6 +58,8 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class HighUsageDetectorTest {
private static final String TAG = "HighUsageDetectorTest";
private static final int UID_HIGH = 123;
private static final int UID_LOW = 345;
private static final double POWER_HIGH = 20000;
@@ -68,6 +75,10 @@ public class HighUsageDetectorTest {
private BatterySipper mSystemBatterySipper;
@Mock
private HighUsageDataParser mDataParser;
@Mock
private BatteryUsageStats mBatteryUsageStats;
@Mock
private BatteryStatsManager mBatteryStatsManager;
private AppInfo mHighAppInfo;
private AppInfo mLowAppInfo;
@@ -80,11 +91,19 @@ public class HighUsageDetectorTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContext = spy(RuntimeEnvironment.application);
mPolicy = spy(new BatteryTipPolicy(mContext));
mBatteryUtils = spy(BatteryUtils.getInstance(mContext));
mBatteryUtils = spy(new BatteryUtils(mContext));
when(mContext.getSystemService(eq(Context.BATTERY_STATS_SERVICE)))
.thenReturn(mBatteryStatsManager);
when(mBatteryStatsManager.getBatteryUsageStats(any(BatteryUsageStatsQuery.class)))
.thenReturn(mBatteryUsageStats);
mContext.sendStickyBroadcast(new Intent(Intent.ACTION_BATTERY_CHANGED));
mHighUsageDetector = spy(new HighUsageDetector(mContext, mPolicy, mBatteryStatsHelper,
true /* mDischarging */));
mBatteryUtils.getBatteryInfo(TAG)));
mHighUsageDetector.mBatteryUtils = mBatteryUtils;
mHighUsageDetector.mDataParser = mDataParser;
doNothing().when(mHighUsageDetector).parseBatteryData();