Snap for 11920703 from 59417f3737 to 24Q3-release
Change-Id: I49463867e9336150bdd2e9d59fab0fa3feaceef1
This commit is contained in:
@@ -95,15 +95,11 @@ android_library {
|
|||||||
"SettingsLibActivityEmbedding",
|
"SettingsLibActivityEmbedding",
|
||||||
"aconfig_settings_flags_lib",
|
"aconfig_settings_flags_lib",
|
||||||
"accessibility_settings_flags_lib",
|
"accessibility_settings_flags_lib",
|
||||||
"app-usage-event-protos-lite",
|
|
||||||
"battery-event-protos-lite",
|
|
||||||
"battery-usage-slot-protos-lite",
|
|
||||||
"contextualcards",
|
"contextualcards",
|
||||||
"development_settings_flag_lib",
|
"development_settings_flag_lib",
|
||||||
"factory_reset_flags_lib",
|
"factory_reset_flags_lib",
|
||||||
"fuelgauge-log-protos-lite",
|
"fuelgauge-log-protos-lite",
|
||||||
"fuelgauge-usage-state-protos-lite",
|
"fuelgauge-protos-lite",
|
||||||
"power-anomaly-event-protos-lite",
|
|
||||||
"settings-contextual-card-protos-lite",
|
"settings-contextual-card-protos-lite",
|
||||||
"settings-log-bridge-protos-lite",
|
"settings-log-bridge-protos-lite",
|
||||||
"settings-logtags",
|
"settings-logtags",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ message BatteryOptimizeHistoricalLogEntry {
|
|||||||
BACKUP = 5;
|
BACKUP = 5;
|
||||||
FORCE_RESET = 6;
|
FORCE_RESET = 6;
|
||||||
EXTERNAL_UPDATE = 7;
|
EXTERNAL_UPDATE = 7;
|
||||||
|
EXPIRATION_RESET = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional string package_name = 1;
|
optional string package_name = 1;
|
||||||
|
|||||||
@@ -121,6 +121,7 @@
|
|||||||
android:title="@string/cellular_security_title"
|
android:title="@string/cellular_security_title"
|
||||||
android:summary="@string/cellular_security_summary"
|
android:summary="@string/cellular_security_summary"
|
||||||
android:fragment="com.android.settings.network.telephony.CellularSecuritySettingsFragment"
|
android:fragment="com.android.settings.network.telephony.CellularSecuritySettingsFragment"
|
||||||
|
settings:controller="com.android.settings.network.CellularSecurityPreferenceController"
|
||||||
settings:searchable="false"/>
|
settings:searchable="false"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|||||||
@@ -210,24 +210,31 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
initializeAllPreferences();
|
initializeAllPreferences();
|
||||||
|
updateAllPreferences();
|
||||||
|
mNeedPreferencesUpdate = false;
|
||||||
registerContentMonitors();
|
registerContentMonitors();
|
||||||
registerInputDeviceListener();
|
registerInputDeviceListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onStart() {
|
||||||
super.onResume();
|
super.onStart();
|
||||||
updateAllPreferences();
|
mIsForeground = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
if (mNeedPreferencesUpdate) {
|
if (mNeedPreferencesUpdate) {
|
||||||
updateAllPreferences();
|
updateAllPreferences();
|
||||||
mNeedPreferencesUpdate = false;
|
mNeedPreferencesUpdate = false;
|
||||||
}
|
}
|
||||||
mIsForeground = true;
|
}
|
||||||
super.onStart();
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
mNeedPreferencesUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import com.android.settings.core.InstrumentedPreferenceFragment;
|
|||||||
import com.android.settings.core.SubSettingLauncher;
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
import com.android.settings.dashboard.DashboardFragment;
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
|
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
|
||||||
|
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils;
|
||||||
import com.android.settings.fuelgauge.batteryusage.BatteryDiffEntry;
|
import com.android.settings.fuelgauge.batteryusage.BatteryDiffEntry;
|
||||||
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
|
import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
@@ -274,9 +275,12 @@ public class AdvancedPowerUsageDetail extends DashboardFragment
|
|||||||
final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
|
final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
|
||||||
mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
|
mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
|
||||||
logMetricCategory(currentOptimizeMode);
|
logMetricCategory(currentOptimizeMode);
|
||||||
|
|
||||||
mExecutor.execute(
|
mExecutor.execute(
|
||||||
() -> {
|
() -> {
|
||||||
|
if (currentOptimizeMode != mOptimizationMode) {
|
||||||
|
AppOptModeSharedPreferencesUtils.deleteAppOptimizationModeEventByUid(
|
||||||
|
getContext(), mBatteryOptimizeUtils.getUid());
|
||||||
|
}
|
||||||
BatteryOptimizeLogUtils.writeLog(
|
BatteryOptimizeLogUtils.writeLog(
|
||||||
getContext().getApplicationContext(),
|
getContext().getApplicationContext(),
|
||||||
Action.LEAVE,
|
Action.LEAVE,
|
||||||
|
|||||||
@@ -182,6 +182,14 @@ public class BatteryOptimizeUtils {
|
|||||||
&& getAppOptimizationMode() != BatteryOptimizeUtils.MODE_RESTRICTED;
|
&& getAppOptimizationMode() != BatteryOptimizeUtils.MODE_RESTRICTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getPackageName() {
|
||||||
|
return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getUid() {
|
||||||
|
return mUid;
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets the list of installed applications. */
|
/** Gets the list of installed applications. */
|
||||||
public static ArraySet<ApplicationInfo> getInstalledApplications(
|
public static ArraySet<ApplicationInfo> getInstalledApplications(
|
||||||
Context context, IPackageManager ipm) {
|
Context context, IPackageManager ipm) {
|
||||||
@@ -257,10 +265,6 @@ public class BatteryOptimizeUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getPackageName() {
|
|
||||||
return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getMode(AppOpsManager appOpsManager, int uid, String packageName) {
|
static int getMode(AppOpsManager appOpsManager, int uid, String packageName) {
|
||||||
return appOpsManager.checkOpNoThrow(
|
return appOpsManager.checkOpNoThrow(
|
||||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName);
|
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.SubSettingLauncher;
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
import com.android.settings.dashboard.DashboardFragment;
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
|
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.widget.EntityHeaderController;
|
import com.android.settings.widget.EntityHeaderController;
|
||||||
import com.android.settingslib.HelpUtils;
|
import com.android.settingslib.HelpUtils;
|
||||||
@@ -121,6 +122,10 @@ public class PowerBackgroundUsageDetail extends DashboardFragment
|
|||||||
|
|
||||||
mExecutor.execute(
|
mExecutor.execute(
|
||||||
() -> {
|
() -> {
|
||||||
|
if (currentOptimizeMode != mOptimizationMode) {
|
||||||
|
AppOptModeSharedPreferencesUtils.deleteAppOptimizationModeEventByUid(
|
||||||
|
getContext(), mBatteryOptimizeUtils.getUid());
|
||||||
|
}
|
||||||
BatteryOptimizeLogUtils.writeLog(
|
BatteryOptimizeLogUtils.writeLog(
|
||||||
getContext().getApplicationContext(),
|
getContext().getApplicationContext(),
|
||||||
Action.LEAVE,
|
Action.LEAVE,
|
||||||
|
|||||||
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.content.SharedPreferences
|
||||||
|
import android.util.ArrayMap
|
||||||
|
import android.util.Base64
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeUtils
|
||||||
|
import com.android.settings.fuelgauge.BatteryUtils
|
||||||
|
|
||||||
|
/** A util to store and update app optimization mode expiration event data. */
|
||||||
|
object AppOptModeSharedPreferencesUtils {
|
||||||
|
private const val TAG: String = "AppOptModeSharedPreferencesUtils"
|
||||||
|
private const val SHARED_PREFS_FILE: String = "app_optimization_mode_shared_prefs"
|
||||||
|
|
||||||
|
@VisibleForTesting const val UNLIMITED_EXPIRE_TIME: Long = -1L
|
||||||
|
|
||||||
|
private val appOptimizationModeLock = Any()
|
||||||
|
private val defaultInstance = AppOptimizationModeEvent.getDefaultInstance()
|
||||||
|
|
||||||
|
/** Returns all app optimization mode events for log. */
|
||||||
|
@JvmStatic
|
||||||
|
fun getAllEvents(context: Context): List<AppOptimizationModeEvent> =
|
||||||
|
synchronized(appOptimizationModeLock) { getAppOptModeEventsMap(context).values.toList() }
|
||||||
|
|
||||||
|
/** Updates the app optimization mode event data. */
|
||||||
|
@JvmStatic
|
||||||
|
fun updateAppOptModeExpiration(
|
||||||
|
context: Context,
|
||||||
|
uids: List<Int>,
|
||||||
|
packageNames: List<String>,
|
||||||
|
optimizationModes: List<Int>,
|
||||||
|
expirationTimes: LongArray,
|
||||||
|
) =
|
||||||
|
// The internal fun with an additional lambda parameter is used to
|
||||||
|
// 1) get true BatteryOptimizeUtils in production environment
|
||||||
|
// 2) get fake BatteryOptimizeUtils for testing environment
|
||||||
|
updateAppOptModeExpirationInternal(
|
||||||
|
context,
|
||||||
|
uids,
|
||||||
|
packageNames,
|
||||||
|
optimizationModes,
|
||||||
|
expirationTimes
|
||||||
|
) { uid: Int, packageName: String ->
|
||||||
|
BatteryOptimizeUtils(context, uid, packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resets the app optimization mode event data since the query timestamp. */
|
||||||
|
@JvmStatic
|
||||||
|
fun resetExpiredAppOptModeBeforeTimestamp(context: Context, queryTimestamp: Long) =
|
||||||
|
synchronized(appOptimizationModeLock) {
|
||||||
|
val eventsMap = getAppOptModeEventsMap(context)
|
||||||
|
val expirationUids = ArrayList<Int>(eventsMap.size)
|
||||||
|
for ((uid, event) in eventsMap) {
|
||||||
|
if (event.expirationTime > queryTimestamp) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
updateBatteryOptimizationMode(
|
||||||
|
context,
|
||||||
|
event.uid,
|
||||||
|
event.packageName,
|
||||||
|
event.resetOptimizationMode,
|
||||||
|
Action.EXPIRATION_RESET,
|
||||||
|
)
|
||||||
|
expirationUids.add(uid)
|
||||||
|
}
|
||||||
|
// Remove the expired AppOptimizationModeEvent data from storage
|
||||||
|
clearSharedPreferences(context, expirationUids)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Deletes all app optimization mode event data with a specific uid. */
|
||||||
|
@JvmStatic
|
||||||
|
fun deleteAppOptimizationModeEventByUid(context: Context, uid: Int) =
|
||||||
|
synchronized(appOptimizationModeLock) { clearSharedPreferences(context, listOf(uid)) }
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
fun updateAppOptModeExpirationInternal(
|
||||||
|
context: Context,
|
||||||
|
uids: List<Int>,
|
||||||
|
packageNames: List<String>,
|
||||||
|
optimizationModes: List<Int>,
|
||||||
|
expirationTimes: LongArray,
|
||||||
|
getBatteryOptimizeUtils: (Int, String) -> BatteryOptimizeUtils
|
||||||
|
) =
|
||||||
|
synchronized(appOptimizationModeLock) {
|
||||||
|
val eventsMap = getAppOptModeEventsMap(context)
|
||||||
|
val expirationEvents: MutableMap<Int, AppOptimizationModeEvent> = ArrayMap()
|
||||||
|
for (i in uids.indices) {
|
||||||
|
val uid = uids[i]
|
||||||
|
val packageName = packageNames[i]
|
||||||
|
val optimizationMode = optimizationModes[i]
|
||||||
|
val originalOptMode: Int =
|
||||||
|
updateBatteryOptimizationMode(
|
||||||
|
context,
|
||||||
|
uid,
|
||||||
|
packageName,
|
||||||
|
optimizationMode,
|
||||||
|
Action.EXTERNAL_UPDATE,
|
||||||
|
getBatteryOptimizeUtils(uid, packageName)
|
||||||
|
)
|
||||||
|
if (originalOptMode == BatteryOptimizeUtils.MODE_UNKNOWN) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Make sure the reset mode is consistent with the expiration event in storage.
|
||||||
|
val resetOptMode = eventsMap[uid]?.resetOptimizationMode ?: originalOptMode
|
||||||
|
val expireTimeMs: Long = expirationTimes[i]
|
||||||
|
if (expireTimeMs != UNLIMITED_EXPIRE_TIME) {
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"setOptimizationMode($packageName) from $originalOptMode " +
|
||||||
|
"to $optimizationMode with expiration time $expireTimeMs",
|
||||||
|
)
|
||||||
|
expirationEvents[uid] =
|
||||||
|
AppOptimizationModeEvent.newBuilder()
|
||||||
|
.setUid(uid)
|
||||||
|
.setPackageName(packageName)
|
||||||
|
.setResetOptimizationMode(resetOptMode)
|
||||||
|
.setExpirationTime(expireTimeMs)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append and update the AppOptimizationModeEvent.
|
||||||
|
if (expirationEvents.isNotEmpty()) {
|
||||||
|
updateSharedPreferences(context, expirationEvents)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
fun updateBatteryOptimizationMode(
|
||||||
|
context: Context,
|
||||||
|
uid: Int,
|
||||||
|
packageName: String,
|
||||||
|
optimizationMode: Int,
|
||||||
|
action: Action,
|
||||||
|
batteryOptimizeUtils: BatteryOptimizeUtils = BatteryOptimizeUtils(context, uid, packageName)
|
||||||
|
): Int {
|
||||||
|
if (!batteryOptimizeUtils.isOptimizeModeMutable) {
|
||||||
|
Log.w(TAG, "Fail to update immutable optimization mode for: $packageName")
|
||||||
|
return BatteryOptimizeUtils.MODE_UNKNOWN
|
||||||
|
}
|
||||||
|
val currentOptMode = batteryOptimizeUtils.appOptimizationMode
|
||||||
|
batteryOptimizeUtils.setAppUsageState(optimizationMode, action)
|
||||||
|
Log.d(
|
||||||
|
TAG,
|
||||||
|
"setAppUsageState($packageName) to $optimizationMode with action = ${action.name}",
|
||||||
|
)
|
||||||
|
return currentOptMode
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSharedPreferences(context: Context): SharedPreferences {
|
||||||
|
return context.applicationContext.getSharedPreferences(
|
||||||
|
SHARED_PREFS_FILE,
|
||||||
|
Context.MODE_PRIVATE,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAppOptModeEventsMap(context: Context): ArrayMap<Int, AppOptimizationModeEvent> {
|
||||||
|
val sharedPreferences = getSharedPreferences(context)
|
||||||
|
val allKeys = sharedPreferences.all?.keys ?: emptySet()
|
||||||
|
if (allKeys.isEmpty()) {
|
||||||
|
return ArrayMap()
|
||||||
|
}
|
||||||
|
val eventsMap = ArrayMap<Int, AppOptimizationModeEvent>(allKeys.size)
|
||||||
|
for (key in allKeys) {
|
||||||
|
sharedPreferences.getString(key, null)?.let {
|
||||||
|
eventsMap[key.toInt()] = deserializeAppOptimizationModeEvent(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eventsMap
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateSharedPreferences(
|
||||||
|
context: Context,
|
||||||
|
eventsMap: Map<Int, AppOptimizationModeEvent>
|
||||||
|
) {
|
||||||
|
val sharedPreferences = getSharedPreferences(context)
|
||||||
|
sharedPreferences.edit().run {
|
||||||
|
for ((uid, event) in eventsMap) {
|
||||||
|
putString(uid.toString(), serializeAppOptimizationModeEvent(event))
|
||||||
|
}
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clearSharedPreferences(context: Context, uids: List<Int>) {
|
||||||
|
val sharedPreferences = getSharedPreferences(context)
|
||||||
|
sharedPreferences.edit().run {
|
||||||
|
for (uid in uids) {
|
||||||
|
remove(uid.toString())
|
||||||
|
}
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun serializeAppOptimizationModeEvent(event: AppOptimizationModeEvent): String {
|
||||||
|
return Base64.encodeToString(event.toByteArray(), Base64.DEFAULT)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun deserializeAppOptimizationModeEvent(
|
||||||
|
encodedProtoString: String
|
||||||
|
): AppOptimizationModeEvent {
|
||||||
|
return BatteryUtils.parseProtoFromString(encodedProtoString, defaultInstance)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -167,6 +167,8 @@ public final class BatteryUsageDataLoader {
|
|||||||
try {
|
try {
|
||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
loadBatteryStatsData(context, isFullChargeStart);
|
loadBatteryStatsData(context, isFullChargeStart);
|
||||||
|
AppOptModeSharedPreferencesUtils.resetExpiredAppOptModeBeforeTimestamp(
|
||||||
|
context, System.currentTimeMillis());
|
||||||
if (!isFullChargeStart) {
|
if (!isFullChargeStart) {
|
||||||
// No app usage data or battery diff data at this time.
|
// No app usage data or battery diff data at this time.
|
||||||
final UserIdsSeries userIdsSeries =
|
final UserIdsSeries userIdsSeries =
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ public final class BugReportContentProvider extends ContentProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
writer.println("dump BatteryUsage and AppUsage states:");
|
writer.println("dump BatteryUsage and AppUsage states:");
|
||||||
|
LogUtils.dumpAppOptimizationModeEventHist(context, writer);
|
||||||
LogUtils.dumpBatteryUsageDatabaseHist(context, writer);
|
LogUtils.dumpBatteryUsageDatabaseHist(context, writer);
|
||||||
LogUtils.dumpAppUsageDatabaseHist(context, writer);
|
LogUtils.dumpAppUsageDatabaseHist(context, writer);
|
||||||
LogUtils.dumpBatteryUsageSlotDatabaseHist(context, writer);
|
LogUtils.dumpBatteryUsageSlotDatabaseHist(context, writer);
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import android.content.Context;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.settings.fuelgauge.BatteryUtils;
|
import com.android.settings.fuelgauge.BatteryUtils;
|
||||||
|
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils;
|
||||||
|
import com.android.settings.fuelgauge.batteryusage.AppOptimizationModeEvent;
|
||||||
import com.android.settings.fuelgauge.batteryusage.BatteryUsageSlot;
|
import com.android.settings.fuelgauge.batteryusage.BatteryUsageSlot;
|
||||||
import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
|
import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
|
||||||
import com.android.settings.fuelgauge.batteryusage.DatabaseUtils;
|
import com.android.settings.fuelgauge.batteryusage.DatabaseUtils;
|
||||||
@@ -47,6 +49,13 @@ public final class LogUtils {
|
|||||||
private static final Duration DUMP_TIME_OFFSET = Duration.ofHours(24);
|
private static final Duration DUMP_TIME_OFFSET = Duration.ofHours(24);
|
||||||
private static final Duration DUMP_TIME_OFFSET_FOR_ENTRY = Duration.ofHours(4);
|
private static final Duration DUMP_TIME_OFFSET_FOR_ENTRY = Duration.ofHours(4);
|
||||||
|
|
||||||
|
static void dumpAppOptimizationModeEventHist(Context context, PrintWriter writer) {
|
||||||
|
writer.println("\n\tApp Optimization Mode Event History:");
|
||||||
|
final List<AppOptimizationModeEvent> events =
|
||||||
|
AppOptModeSharedPreferencesUtils.getAllEvents(context);
|
||||||
|
dumpListItems(writer, events, event -> event);
|
||||||
|
}
|
||||||
|
|
||||||
static void dumpBatteryUsageDatabaseHist(Context context, PrintWriter writer) {
|
static void dumpBatteryUsageDatabaseHist(Context context, PrintWriter writer) {
|
||||||
// Dumps periodic job events.
|
// Dumps periodic job events.
|
||||||
writer.println("\nBattery PeriodicJob History:");
|
writer.println("\nBattery PeriodicJob History:");
|
||||||
|
|||||||
@@ -9,41 +9,9 @@ package {
|
|||||||
}
|
}
|
||||||
|
|
||||||
java_library {
|
java_library {
|
||||||
name: "app-usage-event-protos-lite",
|
name: "fuelgauge-protos-lite",
|
||||||
proto: {
|
proto: {
|
||||||
type: "lite",
|
type: "lite",
|
||||||
},
|
},
|
||||||
srcs: ["app_usage_event.proto"],
|
srcs: ["*.proto"],
|
||||||
}
|
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "battery-event-protos-lite",
|
|
||||||
proto: {
|
|
||||||
type: "lite",
|
|
||||||
},
|
|
||||||
srcs: ["battery_event.proto"],
|
|
||||||
}
|
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "battery-usage-slot-protos-lite",
|
|
||||||
proto: {
|
|
||||||
type: "lite",
|
|
||||||
},
|
|
||||||
srcs: ["battery_usage_slot.proto"],
|
|
||||||
}
|
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "fuelgauge-usage-state-protos-lite",
|
|
||||||
proto: {
|
|
||||||
type: "lite",
|
|
||||||
},
|
|
||||||
srcs: ["fuelgauge_usage_state.proto"],
|
|
||||||
}
|
|
||||||
|
|
||||||
java_library {
|
|
||||||
name: "power-anomaly-event-protos-lite",
|
|
||||||
proto: {
|
|
||||||
type: "lite",
|
|
||||||
},
|
|
||||||
srcs: ["power_anomaly_event.proto"],
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_package = "com.android.settings.fuelgauge.batteryusage";
|
||||||
|
option java_outer_classname = "AppOptimizationModeEventProto";
|
||||||
|
|
||||||
|
message AppOptimizationModeEvents {
|
||||||
|
// Map of uid to AppOptimizationModeEvent
|
||||||
|
map<int32, AppOptimizationModeEvent> events = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AppOptimizationModeEvent {
|
||||||
|
optional int32 uid = 1;
|
||||||
|
optional string package_name = 2;
|
||||||
|
// Value of BatteryUsageSlot.BatteryOptimizationMode, range = [0,3]
|
||||||
|
optional int32 reset_optimization_mode = 3;
|
||||||
|
optional int64 expiration_time = 4;
|
||||||
|
}
|
||||||
@@ -385,6 +385,7 @@ public class AccessibilitySettingsTest {
|
|||||||
|
|
||||||
mFragment.onContentChanged();
|
mFragment.onContentChanged();
|
||||||
mFragment.onStart();
|
mFragment.onStart();
|
||||||
|
mFragment.onResume();
|
||||||
|
|
||||||
RestrictedPreference preference = mFragment.getPreferenceScreen().findPreference(
|
RestrictedPreference preference = mFragment.getPreferenceScreen().findPreference(
|
||||||
COMPONENT_NAME.flattenToString());
|
COMPONENT_NAME.flattenToString());
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadow
|
|||||||
import com.android.settings.testutils.shadow.ShadowThreadUtils;
|
import com.android.settings.testutils.shadow.ShadowThreadUtils;
|
||||||
import com.android.settingslib.widget.ActionButtonsPreference;
|
import com.android.settingslib.widget.ActionButtonsPreference;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Spy;
|
|
||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
@@ -59,7 +59,7 @@ public class AudioStreamButtonControllerTest {
|
|||||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
private static final String KEY = "audio_stream_button";
|
private static final String KEY = "audio_stream_button";
|
||||||
private static final int BROADCAST_ID = 1;
|
private static final int BROADCAST_ID = 1;
|
||||||
@Spy Context mContext = ApplicationProvider.getApplicationContext();
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
@Mock private AudioStreamsHelper mAudioStreamsHelper;
|
@Mock private AudioStreamsHelper mAudioStreamsHelper;
|
||||||
@Mock private PreferenceScreen mScreen;
|
@Mock private PreferenceScreen mScreen;
|
||||||
@Mock private BluetoothLeBroadcastReceiveState mBroadcastReceiveState;
|
@Mock private BluetoothLeBroadcastReceiveState mBroadcastReceiveState;
|
||||||
@@ -80,6 +80,11 @@ public class AudioStreamButtonControllerTest {
|
|||||||
.thenReturn(mPreference);
|
.thenReturn(mPreference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowAudioStreamsHelper.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDisplayPreference_sourceConnected_setDisconnectButton() {
|
public void testDisplayPreference_sourceConnected_setDisconnectButton() {
|
||||||
when(mAudioStreamsHelper.getAllConnectedSources())
|
when(mAudioStreamsHelper.getAllConnectedSources())
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ import com.android.settings.testutils.shadow.ShadowThreadUtils;
|
|||||||
import com.android.settings.widget.EntityHeaderController;
|
import com.android.settings.widget.EntityHeaderController;
|
||||||
import com.android.settingslib.widget.LayoutPreference;
|
import com.android.settingslib.widget.LayoutPreference;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Spy;
|
|
||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
@@ -61,7 +61,7 @@ public class AudioStreamHeaderControllerTest {
|
|||||||
private static final String KEY = "audio_stream_header";
|
private static final String KEY = "audio_stream_header";
|
||||||
private static final int BROADCAST_ID = 1;
|
private static final int BROADCAST_ID = 1;
|
||||||
private static final String BROADCAST_NAME = "broadcast name";
|
private static final String BROADCAST_NAME = "broadcast name";
|
||||||
@Spy Context mContext = ApplicationProvider.getApplicationContext();
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
@Mock private AudioStreamsHelper mAudioStreamsHelper;
|
@Mock private AudioStreamsHelper mAudioStreamsHelper;
|
||||||
@Mock private PreferenceScreen mScreen;
|
@Mock private PreferenceScreen mScreen;
|
||||||
@Mock private BluetoothLeBroadcastReceiveState mBroadcastReceiveState;
|
@Mock private BluetoothLeBroadcastReceiveState mBroadcastReceiveState;
|
||||||
@@ -81,6 +81,12 @@ public class AudioStreamHeaderControllerTest {
|
|||||||
when(mPreference.getContext()).thenReturn(mContext);
|
when(mPreference.getContext()).thenReturn(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowEntityHeaderController.reset();
|
||||||
|
ShadowAudioStreamsHelper.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDisplayPreference_sourceConnected_setSummary() {
|
public void testDisplayPreference_sourceConnected_setSummary() {
|
||||||
when(mAudioStreamsHelper.getAllConnectedSources())
|
when(mAudioStreamsHelper.getAllConnectedSources())
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import android.view.View;
|
|||||||
|
|
||||||
import androidx.preference.Preference.OnPreferenceClickListener;
|
import androidx.preference.Preference.OnPreferenceClickListener;
|
||||||
import androidx.preference.PreferenceViewHolder;
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.AudioStreamState;
|
import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsProgressCategoryController.AudioStreamState;
|
||||||
@@ -42,7 +43,6 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ public class AudioStreamPreferenceTest {
|
|||||||
private static final String PROGRAM_NAME = "program_name";
|
private static final String PROGRAM_NAME = "program_name";
|
||||||
private static final int BROADCAST_RSSI = 1;
|
private static final int BROADCAST_RSSI = 1;
|
||||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
private Context mContext;
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
private AudioStreamPreference mPreference;
|
private AudioStreamPreference mPreference;
|
||||||
@Mock private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata;
|
@Mock private BluetoothLeBroadcastMetadata mBluetoothLeBroadcastMetadata;
|
||||||
@Mock private BluetoothLeBroadcastReceiveState mBluetoothLeBroadcastReceiveState;
|
@Mock private BluetoothLeBroadcastReceiveState mBluetoothLeBroadcastReceiveState;
|
||||||
@@ -61,7 +61,6 @@ public class AudioStreamPreferenceTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mContext = RuntimeEnvironment.application;
|
|
||||||
mPreference = new AudioStreamPreference(mContext, null);
|
mPreference = new AudioStreamPreference(mContext, null);
|
||||||
when(mBluetoothLeBroadcastMetadata.getBroadcastId()).thenReturn(BROADCAST_ID);
|
when(mBluetoothLeBroadcastMetadata.getBroadcastId()).thenReturn(BROADCAST_ID);
|
||||||
when(mBluetoothLeBroadcastMetadata.getBroadcastName()).thenReturn(BROADCAST_NAME);
|
when(mBluetoothLeBroadcastMetadata.getBroadcastName()).thenReturn(BROADCAST_NAME);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import android.content.Context;
|
|||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
@@ -37,7 +38,6 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
public class AudioStreamsActiveDeviceControllerTest {
|
public class AudioStreamsActiveDeviceControllerTest {
|
||||||
@@ -48,7 +48,7 @@ public class AudioStreamsActiveDeviceControllerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
Context context = RuntimeEnvironment.application;
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
mController =
|
mController =
|
||||||
new AudioStreamsActiveDeviceController(
|
new AudioStreamsActiveDeviceController(
|
||||||
context, AudioStreamsActiveDeviceController.KEY);
|
context, AudioStreamsActiveDeviceController.KEY);
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ import com.android.settings.R;
|
|||||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Spy;
|
|
||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
@@ -49,7 +49,7 @@ import org.robolectric.annotation.Config;
|
|||||||
public class AudioStreamsActiveDeviceSummaryUpdaterTest {
|
public class AudioStreamsActiveDeviceSummaryUpdaterTest {
|
||||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
private static final String DEVICE_NAME = "device_name";
|
private static final String DEVICE_NAME = "device_name";
|
||||||
@Spy private final Context mContext = ApplicationProvider.getApplicationContext();
|
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||||
private final AudioStreamsActiveDeviceSummaryUpdater.OnSummaryChangeListener mFakeListener =
|
private final AudioStreamsActiveDeviceSummaryUpdater.OnSummaryChangeListener mFakeListener =
|
||||||
summary -> mUpdatedSummary = summary;
|
summary -> mUpdatedSummary = summary;
|
||||||
@Mock private CachedBluetoothDevice mCachedBluetoothDevice;
|
@Mock private CachedBluetoothDevice mCachedBluetoothDevice;
|
||||||
@@ -60,10 +60,14 @@ public class AudioStreamsActiveDeviceSummaryUpdaterTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
|
ShadowAudioStreamsHelper.setUseMock(mAudioStreamsHelper);
|
||||||
ShadowAudioStreamsHelper.resetCachedBluetoothDevice();
|
|
||||||
mUpdater = new AudioStreamsActiveDeviceSummaryUpdater(mContext, mFakeListener);
|
mUpdater = new AudioStreamsActiveDeviceSummaryUpdater(mContext, mFakeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowAudioStreamsHelper.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void register_summaryUpdated() {
|
public void register_summaryUpdated() {
|
||||||
mUpdater.register(true);
|
mUpdater.register(true);
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import android.media.session.MediaController;
|
|||||||
import android.media.session.MediaSessionManager;
|
import android.media.session.MediaSessionManager;
|
||||||
import android.media.session.PlaybackState;
|
import android.media.session.PlaybackState;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowAudioStreamsHelper;
|
||||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowLocalMediaManager;
|
import com.android.settings.connecteddevice.audiosharing.audiostreams.testshadows.ShadowLocalMediaManager;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
@@ -30,6 +32,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
|||||||
import com.android.settingslib.media.BluetoothMediaDevice;
|
import com.android.settingslib.media.BluetoothMediaDevice;
|
||||||
import com.android.settingslib.media.LocalMediaManager;
|
import com.android.settingslib.media.LocalMediaManager;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -38,7 +41,6 @@ import org.mockito.Mock;
|
|||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -64,15 +66,20 @@ public class MediaControlHelperTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mContext = spy(RuntimeEnvironment.application);
|
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||||
when(mContext.getSystemService(MediaSessionManager.class)).thenReturn(mMediaSessionManager);
|
when(mContext.getSystemService(MediaSessionManager.class)).thenReturn(mMediaSessionManager);
|
||||||
when(mMediaSessionManager.getActiveSessions(any())).thenReturn(List.of(mMediaController));
|
when(mMediaSessionManager.getActiveSessions(any())).thenReturn(List.of(mMediaController));
|
||||||
when(mMediaController.getPackageName()).thenReturn(FAKE_PACKAGE);
|
when(mMediaController.getPackageName()).thenReturn(FAKE_PACKAGE);
|
||||||
when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
|
when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
|
||||||
ShadowAudioStreamsHelper.resetCachedBluetoothDevice();
|
|
||||||
ShadowLocalMediaManager.setUseMock(mLocalMediaManager);
|
ShadowLocalMediaManager.setUseMock(mLocalMediaManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowAudioStreamsHelper.reset();
|
||||||
|
ShadowLocalMediaManager.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStart_noBluetoothManager_doNothing() {
|
public void testStart_noBluetoothManager_doNothing() {
|
||||||
MediaControlHelper helper = new MediaControlHelper(mContext, null);
|
MediaControlHelper helper = new MediaControlHelper(mContext, null);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import static com.android.settings.connecteddevice.audiosharing.audiostreams.Aud
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
|
import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
|
||||||
@@ -33,6 +32,7 @@ import android.content.Context;
|
|||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -60,10 +60,15 @@ public class SyncedStateTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
ShadowAlertDialog.reset();
|
ShadowAlertDialog.reset();
|
||||||
mMockContext = spy(ApplicationProvider.getApplicationContext());
|
mMockContext = ApplicationProvider.getApplicationContext();
|
||||||
mInstance = SyncedState.getInstance();
|
mInstance = SyncedState.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
ShadowAlertDialog.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetInstance() {
|
public void testGetInstance() {
|
||||||
assertThat(mInstance).isNotNull();
|
assertThat(mInstance).isNotNull();
|
||||||
|
|||||||
@@ -18,12 +18,15 @@ package com.android.settings.connecteddevice.audiosharing.audiostreams.testshado
|
|||||||
|
|
||||||
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
import android.bluetooth.BluetoothLeBroadcastReceiveState;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsHelper;
|
import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsHelper;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||||
|
|
||||||
import org.robolectric.annotation.Implementation;
|
import org.robolectric.annotation.Implementation;
|
||||||
import org.robolectric.annotation.Implements;
|
import org.robolectric.annotation.Implements;
|
||||||
|
import org.robolectric.annotation.Resetter;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -31,20 +34,22 @@ import java.util.Optional;
|
|||||||
@Implements(value = AudioStreamsHelper.class, callThroughByDefault = false)
|
@Implements(value = AudioStreamsHelper.class, callThroughByDefault = false)
|
||||||
public class ShadowAudioStreamsHelper {
|
public class ShadowAudioStreamsHelper {
|
||||||
private static AudioStreamsHelper sMockHelper;
|
private static AudioStreamsHelper sMockHelper;
|
||||||
private static Optional<CachedBluetoothDevice> sCachedBluetoothDevice;
|
@Nullable private static CachedBluetoothDevice sCachedBluetoothDevice;
|
||||||
|
|
||||||
public static void setUseMock(AudioStreamsHelper mockAudioStreamsHelper) {
|
public static void setUseMock(AudioStreamsHelper mockAudioStreamsHelper) {
|
||||||
sMockHelper = mockAudioStreamsHelper;
|
sMockHelper = mockAudioStreamsHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resets {@link CachedBluetoothDevice} */
|
/** Reset static fields */
|
||||||
public static void resetCachedBluetoothDevice() {
|
@Resetter
|
||||||
sCachedBluetoothDevice = Optional.empty();
|
public static void reset() {
|
||||||
|
sMockHelper = null;
|
||||||
|
sCachedBluetoothDevice = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setCachedBluetoothDeviceInSharingOrLeConnected(
|
public static void setCachedBluetoothDeviceInSharingOrLeConnected(
|
||||||
CachedBluetoothDevice cachedBluetoothDevice) {
|
CachedBluetoothDevice cachedBluetoothDevice) {
|
||||||
sCachedBluetoothDevice = Optional.of(cachedBluetoothDevice);
|
sCachedBluetoothDevice = cachedBluetoothDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Implementation
|
@Implementation
|
||||||
@@ -56,6 +61,6 @@ public class ShadowAudioStreamsHelper {
|
|||||||
@Implementation
|
@Implementation
|
||||||
public static Optional<CachedBluetoothDevice> getCachedBluetoothDeviceInSharingOrLeConnected(
|
public static Optional<CachedBluetoothDevice> getCachedBluetoothDeviceInSharingOrLeConnected(
|
||||||
LocalBluetoothManager manager) {
|
LocalBluetoothManager manager) {
|
||||||
return sCachedBluetoothDevice;
|
return Optional.ofNullable(sCachedBluetoothDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import com.android.settings.widget.EntityHeaderController;
|
|||||||
|
|
||||||
import org.robolectric.annotation.Implementation;
|
import org.robolectric.annotation.Implementation;
|
||||||
import org.robolectric.annotation.Implements;
|
import org.robolectric.annotation.Implements;
|
||||||
|
import org.robolectric.annotation.Resetter;
|
||||||
|
|
||||||
@Implements(value = EntityHeaderController.class, callThroughByDefault = false)
|
@Implements(value = EntityHeaderController.class, callThroughByDefault = false)
|
||||||
public class ShadowEntityHeaderController {
|
public class ShadowEntityHeaderController {
|
||||||
@@ -34,6 +35,12 @@ public class ShadowEntityHeaderController {
|
|||||||
sMockController = mockController;
|
sMockController = mockController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Reset static fields */
|
||||||
|
@Resetter
|
||||||
|
public static void reset() {
|
||||||
|
sMockController = null;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns new instance of {@link EntityHeaderController} */
|
/** Returns new instance of {@link EntityHeaderController} */
|
||||||
@Implementation
|
@Implementation
|
||||||
public static EntityHeaderController newInstance(
|
public static EntityHeaderController newInstance(
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.android.settingslib.media.MediaDevice;
|
|||||||
|
|
||||||
import org.robolectric.annotation.Implementation;
|
import org.robolectric.annotation.Implementation;
|
||||||
import org.robolectric.annotation.Implements;
|
import org.robolectric.annotation.Implements;
|
||||||
|
import org.robolectric.annotation.Resetter;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@@ -34,6 +35,13 @@ public class ShadowLocalMediaManager {
|
|||||||
sMockManager = mockLocalMediaManager;
|
sMockManager = mockLocalMediaManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Reset static fields */
|
||||||
|
@Resetter
|
||||||
|
public static void reset() {
|
||||||
|
sMockManager = null;
|
||||||
|
sDeviceCallback = null;
|
||||||
|
}
|
||||||
|
|
||||||
/** Triggers onDeviceListUpdate of {@link LocalMediaManager.DeviceCallback} */
|
/** Triggers onDeviceListUpdate of {@link LocalMediaManager.DeviceCallback} */
|
||||||
public static void onDeviceListUpdate() {
|
public static void onDeviceListUpdate() {
|
||||||
sDeviceCallback.onDeviceListUpdate(Collections.emptyList());
|
sDeviceCallback.onDeviceListUpdate(Collections.emptyList());
|
||||||
|
|||||||
@@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.test.core.app.ApplicationProvider
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeUtils
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_OPTIMIZED
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_RESTRICTED
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNKNOWN
|
||||||
|
import com.android.settings.fuelgauge.BatteryOptimizeUtils.MODE_UNRESTRICTED
|
||||||
|
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils.UNLIMITED_EXPIRE_TIME
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentMatchers.any
|
||||||
|
import org.mockito.Mockito.anyInt
|
||||||
|
import org.mockito.Mockito.never
|
||||||
|
import org.mockito.Mockito.spy
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.Mockito.`when` as whenever
|
||||||
|
import org.mockito.Spy
|
||||||
|
import org.mockito.junit.MockitoJUnit
|
||||||
|
import org.mockito.junit.MockitoRule
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
class AppOptModeSharedPreferencesUtilsTest {
|
||||||
|
@JvmField @Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
|
||||||
|
|
||||||
|
@Spy private var context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
|
||||||
|
@Spy
|
||||||
|
private var testBatteryOptimizeUtils = spy(BatteryOptimizeUtils(context, UID, PACKAGE_NAME))
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
AppOptModeSharedPreferencesUtils.deleteAppOptimizationModeEventByUid(context, UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getAllEvents_emptyData_verifyEmptyList() {
|
||||||
|
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updateAppOptModeExpirationInternal_withExpirationTime_verifyData() {
|
||||||
|
insertAppOptModeEventForTest(/* expirationTime= */ 1000L)
|
||||||
|
|
||||||
|
val events = AppOptModeSharedPreferencesUtils.getAllEvents(context)
|
||||||
|
|
||||||
|
assertThat(events.size).isEqualTo(1)
|
||||||
|
assertAppOptimizationModeEventInfo(events.get(0), UID, PACKAGE_NAME, MODE_OPTIMIZED, 1000L)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updateAppOptModeExpirationInternal_withoutExpirationTime_verifyEmptyList() {
|
||||||
|
insertAppOptModeEventForTest(/* expirationTime= */ UNLIMITED_EXPIRE_TIME)
|
||||||
|
|
||||||
|
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deleteAppOptimizationModeEventByUid_uidNotContained_verifyData() {
|
||||||
|
insertAppOptModeEventForTest(/* expirationTime= */ 1000L)
|
||||||
|
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context).size).isEqualTo(1)
|
||||||
|
|
||||||
|
AppOptModeSharedPreferencesUtils.deleteAppOptimizationModeEventByUid(context, UNSET_UID)
|
||||||
|
val events = AppOptModeSharedPreferencesUtils.getAllEvents(context)
|
||||||
|
|
||||||
|
assertThat(events.size).isEqualTo(1)
|
||||||
|
assertAppOptimizationModeEventInfo(events.get(0), UID, PACKAGE_NAME, MODE_OPTIMIZED, 1000L)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deleteAppOptimizationModeEventByUid_uidExisting_verifyData() {
|
||||||
|
insertAppOptModeEventForTest(/* expirationTime= */ 1000L)
|
||||||
|
|
||||||
|
AppOptModeSharedPreferencesUtils.deleteAppOptimizationModeEventByUid(context, UID)
|
||||||
|
|
||||||
|
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun resetExpiredAppOptModeBeforeTimestamp_noExpiredData_verifyData() {
|
||||||
|
insertAppOptModeEventForTest(/* expirationTime= */ 1000L)
|
||||||
|
|
||||||
|
AppOptModeSharedPreferencesUtils.resetExpiredAppOptModeBeforeTimestamp(context, 999L)
|
||||||
|
val events = AppOptModeSharedPreferencesUtils.getAllEvents(context)
|
||||||
|
|
||||||
|
assertThat(events.size).isEqualTo(1)
|
||||||
|
assertAppOptimizationModeEventInfo(events.get(0), UID, PACKAGE_NAME, MODE_OPTIMIZED, 1000L)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun resetExpiredAppOptModeBeforeTimestamp_hasExpiredData_verifyEmptyList() {
|
||||||
|
insertAppOptModeEventForTest(/* expirationTime= */ 1000L)
|
||||||
|
|
||||||
|
AppOptModeSharedPreferencesUtils.resetExpiredAppOptModeBeforeTimestamp(context, 1001L)
|
||||||
|
|
||||||
|
assertThat(AppOptModeSharedPreferencesUtils.getAllEvents(context)).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updateBatteryOptimizationMode_updateToOptimizedMode_verifyAction() {
|
||||||
|
whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(true)
|
||||||
|
whenever(testBatteryOptimizeUtils?.getAppOptimizationMode(true))
|
||||||
|
.thenReturn(MODE_UNRESTRICTED)
|
||||||
|
|
||||||
|
val currentOptMode =
|
||||||
|
AppOptModeSharedPreferencesUtils.updateBatteryOptimizationMode(
|
||||||
|
context,
|
||||||
|
UID,
|
||||||
|
PACKAGE_NAME,
|
||||||
|
MODE_OPTIMIZED,
|
||||||
|
Action.EXTERNAL_UPDATE,
|
||||||
|
testBatteryOptimizeUtils
|
||||||
|
)
|
||||||
|
|
||||||
|
verify(testBatteryOptimizeUtils)?.setAppUsageState(MODE_OPTIMIZED, Action.EXTERNAL_UPDATE)
|
||||||
|
assertThat(currentOptMode).isEqualTo(MODE_UNRESTRICTED)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updateBatteryOptimizationMode_optimizationModeNotChanged_verifyAction() {
|
||||||
|
whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(false)
|
||||||
|
whenever(testBatteryOptimizeUtils?.getAppOptimizationMode(true))
|
||||||
|
.thenReturn(MODE_UNRESTRICTED)
|
||||||
|
|
||||||
|
val currentOptMode =
|
||||||
|
AppOptModeSharedPreferencesUtils.updateBatteryOptimizationMode(
|
||||||
|
context,
|
||||||
|
UID,
|
||||||
|
PACKAGE_NAME,
|
||||||
|
MODE_OPTIMIZED,
|
||||||
|
Action.EXTERNAL_UPDATE,
|
||||||
|
testBatteryOptimizeUtils
|
||||||
|
)
|
||||||
|
|
||||||
|
verify(testBatteryOptimizeUtils, never())?.setAppUsageState(anyInt(), any())
|
||||||
|
assertThat(currentOptMode).isEqualTo(MODE_UNKNOWN)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updateBatteryOptimizationMode_updateToSameOptimizationMode_verifyAction() {
|
||||||
|
whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(true)
|
||||||
|
whenever(testBatteryOptimizeUtils?.getAppOptimizationMode(true)).thenReturn(MODE_RESTRICTED)
|
||||||
|
|
||||||
|
val currentOptMode =
|
||||||
|
AppOptModeSharedPreferencesUtils.updateBatteryOptimizationMode(
|
||||||
|
context,
|
||||||
|
UID,
|
||||||
|
PACKAGE_NAME,
|
||||||
|
MODE_RESTRICTED,
|
||||||
|
Action.EXTERNAL_UPDATE,
|
||||||
|
testBatteryOptimizeUtils
|
||||||
|
)
|
||||||
|
|
||||||
|
verify(testBatteryOptimizeUtils)?.setAppUsageState(MODE_RESTRICTED, Action.EXTERNAL_UPDATE)
|
||||||
|
assertThat(currentOptMode).isEqualTo(MODE_RESTRICTED)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun insertAppOptModeEventForTest(expirationTime: Long) {
|
||||||
|
whenever(testBatteryOptimizeUtils?.isOptimizeModeMutable).thenReturn(true)
|
||||||
|
whenever(testBatteryOptimizeUtils?.getAppOptimizationMode(true)).thenReturn(MODE_OPTIMIZED)
|
||||||
|
AppOptModeSharedPreferencesUtils.updateAppOptModeExpirationInternal(
|
||||||
|
context,
|
||||||
|
mutableListOf(UID),
|
||||||
|
mutableListOf(PACKAGE_NAME),
|
||||||
|
mutableListOf(MODE_OPTIMIZED),
|
||||||
|
longArrayOf(expirationTime)
|
||||||
|
) { _: Int, _: String ->
|
||||||
|
testBatteryOptimizeUtils
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val UID: Int = 12345
|
||||||
|
const val UNSET_UID: Int = 15432
|
||||||
|
const val PACKAGE_NAME: String = "com.android.app"
|
||||||
|
|
||||||
|
private fun assertAppOptimizationModeEventInfo(
|
||||||
|
event: AppOptimizationModeEvent,
|
||||||
|
uid: Int,
|
||||||
|
packageName: String,
|
||||||
|
resetOptimizationMode: Int,
|
||||||
|
expirationTime: Long
|
||||||
|
) {
|
||||||
|
assertThat(event.uid).isEqualTo(uid)
|
||||||
|
assertThat(event.packageName).isEqualTo(packageName)
|
||||||
|
assertThat(event.resetOptimizationMode).isEqualTo(resetOptimizationMode)
|
||||||
|
assertThat(event.expirationTime).isEqualTo(expirationTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -189,8 +189,8 @@ public class ApprovalPreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@EnableFlags(Flags.FLAG_MODES_API)
|
@EnableFlags(Flags.FLAG_MODES_API)
|
||||||
@Ignore("b/339550695")
|
|
||||||
public void disable() {
|
public void disable() {
|
||||||
|
when(mNm.isNotificationPolicyAccessGrantedForPackage(anyString())).thenReturn(false);
|
||||||
mController.disable(mCn);
|
mController.disable(mCn);
|
||||||
verify(mFeatureFactory.metricsFeatureProvider).action(
|
verify(mFeatureFactory.metricsFeatureProvider).action(
|
||||||
mContext,
|
mContext,
|
||||||
|
|||||||
Reference in New Issue
Block a user