Snap for 11348195 from b6e28eeda5 to 24Q2-release
Change-Id: Idf38dabe0ac8c950dd3e05103f47694ff6eede76
This commit is contained in:
@@ -719,9 +719,9 @@
|
||||
<!-- An explanation text that the password needs to be solved because the device was factory reset. [CHAR LIMIT=100] -->
|
||||
<string name="lockpassword_confirm_your_password_details_frp" product="device">Your device was reset to factory settings. To use this device, enter your previous password.</string>
|
||||
<!-- Message of incompatible charging battery tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_incompatible_charging_message" product="default">Battery charging slowly or won\'t charge. Check if the cable and power adapter work with your phone</string>
|
||||
<string name="battery_tip_incompatible_charging_message" product="device">Battery charging slowly or won\'t charge. Check if the cable and power adapter work with your device</string>
|
||||
<string name="battery_tip_incompatible_charging_message" product="tablet">Battery charging slowly or won\'t charge. Check if the cable and power adapter work with your tablet</string>
|
||||
<string name="battery_tip_incompatible_charging_message" product="default">Your phone may be charging slowly or not charging. For faster charging, use a recommended cable and adapter.</string>
|
||||
<string name="battery_tip_incompatible_charging_message" product="device">Your device may be charging slowly or not charging. For faster charging, use a recommended cable and adapter.</string>
|
||||
<string name="battery_tip_incompatible_charging_message" product="tablet">Your tablet may be charging slowly or not charging. For faster charging, use a recommended cable and adapter.</string>
|
||||
|
||||
<!-- Description for using device controls feature with a locked phone [CHAR LIMIT=NONE] -->
|
||||
<string name="lockscreen_trivial_controls_summary" product="default">Without unlocking your phone</string>
|
||||
|
||||
25
res/drawable/ic_battery_incompatible_charger.xml
Normal file
25
res/drawable/ic_battery_incompatible_charger.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="33dp"
|
||||
android:height="33dp"
|
||||
android:viewportWidth="33"
|
||||
android:viewportHeight="33">
|
||||
<path
|
||||
android:pathData="M29.136,29.137L3.864,3.864L1.911,5.803L8.278,12.169C8.278,12.224 8.25,19.938 8.25,19.938L13.063,24.75V28.875H19.938V24.75L20.405,24.283L27.198,31.076L29.136,29.137ZM17.188,23.609V26.125H15.813V23.609L11,18.769V14.878L18.452,22.33L17.188,23.609ZM11,7.109L16.266,12.375H22V18.109L24.282,20.392L24.75,19.924V12.375C24.75,10.863 23.513,9.626 22,9.626V4.126H19.25V9.626H13.75V4.126H11V7.109Z"
|
||||
android:fillColor="?android:attr/colorAccent"/>
|
||||
</vector>
|
||||
@@ -5612,18 +5612,6 @@
|
||||
<string name="battery_tip_limited_temporarily_title">Charging optimized to protect your battery</string>
|
||||
<!-- Summary for the battery limited temporarily tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_limited_temporarily_summary">To help extend your battery\'s lifespan, charging is optimized</string>
|
||||
<!-- Title for the battery dock defender future bypass tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_dock_defender_future_bypass_title">Charging optimized to protect your battery</string>
|
||||
<!-- Summary for the battery dock defender future bypass tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_dock_defender_future_bypass_summary">To help extend your battery\'s lifespan, charging is optimized while docked</string>
|
||||
<!-- Title for the battery dock defender active tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_dock_defender_active_title">Charging optimized to protect your battery</string>
|
||||
<!-- Summary for the battery dock defender active tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_dock_defender_active_summary">To help extend your battery\'s lifespan, charging is optimized while docked</string>
|
||||
<!-- Title for the battery dock defender temporarily bypassed tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_dock_defender_temporarily_bypassed_title">Charging to full</string>
|
||||
<!-- Summary for the battery dock defender temporarily bypassed tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_dock_defender_temporarily_bypassed_summary">To protect your battery, charging will be optimized the next time your tablet is docked</string>
|
||||
<!-- Content description for the battery limited temporarily tip secondary button [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_limited_temporarily_sec_button_content_description">Learn more about charging is paused</string>
|
||||
<!-- Text of battery limited temporarily tip resume charge button. [CHAR LIMIT=NONE] -->
|
||||
@@ -5675,7 +5663,7 @@
|
||||
<!-- Charge to full button for battery defender tips [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_charge_to_full_button">Charge to full</string>
|
||||
<!-- Title of incompatible charging battery tip [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_incompatible_charging_title">Issue with charging accessory</string>
|
||||
<string name="battery_tip_incompatible_charging_title">Check charging accessory</string>
|
||||
<!-- Content description for the incompatible charging battery tip button [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_incompatible_charging_content_description">Learn more about incompatible charging</string>
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
android:order="10"
|
||||
android:title="@string/app_notification_field"
|
||||
android:summary="@string/app_notification_field_summary"
|
||||
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
|
||||
settings:searchable="false">
|
||||
android:fragment="com.android.settings.applications.manageapplications.ManageApplications">
|
||||
<extra
|
||||
android:name="classname"
|
||||
android:value="com.android.settings.Settings$NotificationAppListActivity"/>
|
||||
|
||||
@@ -64,7 +64,7 @@ public abstract class TelecomUtil {
|
||||
return Optional.empty();
|
||||
}
|
||||
SubscriptionManager subscriptionManager = context.getSystemService(
|
||||
SubscriptionManager.class);
|
||||
SubscriptionManager.class).createForAllUserProfiles();
|
||||
List<SubscriptionInfo> subscriptionInfos =
|
||||
subscriptionManager.getActiveSubscriptionInfoList();
|
||||
if (subscriptionInfos == null) {
|
||||
|
||||
@@ -59,6 +59,7 @@ import com.android.settings.applications.manageapplications.ManageApplications.L
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_WIFI_ACCESS
|
||||
import com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_WRITE_SETTINGS
|
||||
import com.android.settings.spa.app.AllAppListPageProvider
|
||||
import com.android.settings.spa.app.battery.BatteryOptimizationModeAppListPageProvider
|
||||
import com.android.settings.spa.app.appcompat.UserAspectRatioAppsPageProvider
|
||||
import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
|
||||
import com.android.settings.spa.app.specialaccess.AllFilesAccessAppListProvider
|
||||
@@ -70,7 +71,6 @@ import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListPro
|
||||
import com.android.settings.spa.app.specialaccess.NfcTagAppsSettingsProvider
|
||||
import com.android.settings.spa.app.specialaccess.TurnScreenOnAppsAppListProvider
|
||||
import com.android.settings.spa.app.specialaccess.WifiControlAppListProvider
|
||||
import com.android.settings.spa.app.storage.StorageAppListPageProvider
|
||||
import com.android.settings.spa.notification.AppListNotificationsPageProvider
|
||||
import com.android.settings.spa.system.AppLanguagesPageProvider
|
||||
|
||||
@@ -127,6 +127,7 @@ object ManageApplicationsUtil {
|
||||
// TODO(b/292165031) enable once sorting is supported
|
||||
//LIST_TYPE_STORAGE -> StorageAppListPageProvider.Apps.name
|
||||
//LIST_TYPE_GAMES -> StorageAppListPageProvider.Games.name
|
||||
LIST_TYPE_BATTERY_OPTIMIZATION -> BatteryOptimizationModeAppListPageProvider.name
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,11 +112,28 @@ public class BatteryOptimizeUtils {
|
||||
|
||||
/** Gets the {@link OptimizationMode} for associated app. */
|
||||
@OptimizationMode
|
||||
public int getAppOptimizationMode() {
|
||||
refreshState();
|
||||
public int getAppOptimizationMode(boolean refreshList) {
|
||||
if (refreshList) {
|
||||
mPowerAllowListBackend.refreshList();
|
||||
}
|
||||
mAllowListed = mPowerAllowListBackend.isAllowlisted(mPackageName, mUid);
|
||||
mMode =
|
||||
mAppOpsManager.checkOpNoThrow(
|
||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName);
|
||||
Log.d(
|
||||
TAG,
|
||||
String.format(
|
||||
"refresh %s state, allowlisted = %s, mode = %d",
|
||||
mPackageName, mAllowListed, mMode));
|
||||
return getAppOptimizationMode(mMode, mAllowListed);
|
||||
}
|
||||
|
||||
/** Gets the {@link OptimizationMode} for associated app. */
|
||||
@OptimizationMode
|
||||
public int getAppOptimizationMode() {
|
||||
return getAppOptimizationMode(true);
|
||||
}
|
||||
|
||||
/** Resets optimization mode for all applications. */
|
||||
public static void resetAppOptimizationMode(
|
||||
Context context, IPackageManager ipm, AppOpsManager aom) {
|
||||
@@ -336,19 +353,6 @@ public class BatteryOptimizeUtils {
|
||||
context, action, packageNameKey, createLogEvent(appStandbyMode, allowListed));
|
||||
}
|
||||
|
||||
private void refreshState() {
|
||||
mPowerAllowListBackend.refreshList();
|
||||
mAllowListed = mPowerAllowListBackend.isAllowlisted(mPackageName, mUid);
|
||||
mMode =
|
||||
mAppOpsManager.checkOpNoThrow(
|
||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mPackageName);
|
||||
Log.d(
|
||||
TAG,
|
||||
String.format(
|
||||
"refresh %s state, allowlisted = %s, mode = %d",
|
||||
mPackageName, mAllowListed, mMode));
|
||||
}
|
||||
|
||||
private static String createLogEvent(int appStandbyMode, boolean allowListed) {
|
||||
return appStandbyMode < 0
|
||||
? "Apply optimize setting ERROR"
|
||||
|
||||
@@ -35,5 +35,5 @@ public interface BatterySettingsFeatureProvider {
|
||||
boolean isBatteryInfoEnabled(Context context);
|
||||
|
||||
/** A way to add more battery tip detectors. */
|
||||
void addBatteryTipDetector(Context context, List<BatteryTip> tips);
|
||||
void addBatteryTipDetector(Context context, List<BatteryTip> tips, BatteryInfo batteryInfo);
|
||||
}
|
||||
|
||||
@@ -41,5 +41,6 @@ public class BatterySettingsFeatureProviderImpl implements BatterySettingsFeatur
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBatteryTipDetector(Context context, List<BatteryTip> tips) {}
|
||||
public void addBatteryTipDetector(
|
||||
Context context, List<BatteryTip> tips, BatteryInfo batteryInfo) {}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
import com.android.settings.fuelgauge.BatteryInfo;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.batterytip.detectors.BatteryDefenderDetector;
|
||||
import com.android.settings.fuelgauge.batterytip.detectors.DockDefenderDetector;
|
||||
import com.android.settings.fuelgauge.batterytip.detectors.HighUsageDetector;
|
||||
import com.android.settings.fuelgauge.batterytip.detectors.IncompatibleChargerDetector;
|
||||
import com.android.settings.fuelgauge.batterytip.detectors.LowBatteryDetector;
|
||||
@@ -66,11 +65,10 @@ public class BatteryTipLoader extends AsyncLoaderCompat<List<BatteryTip>> {
|
||||
tips.add(new LowBatteryDetector(context, policy, batteryInfo, isPowerSaveMode).detect());
|
||||
tips.add(new HighUsageDetector(context, policy, mBatteryUsageStats, batteryInfo).detect());
|
||||
tips.add(new BatteryDefenderDetector(batteryInfo, context).detect());
|
||||
tips.add(new DockDefenderDetector(batteryInfo, context).detect());
|
||||
tips.add(new IncompatibleChargerDetector(context).detect());
|
||||
FeatureFactory.getFeatureFactory()
|
||||
.getBatterySettingsFeatureProvider()
|
||||
.addBatteryTipDetector(context, tips);
|
||||
.addBatteryTipDetector(context, tips, batteryInfo);
|
||||
Collections.sort(tips);
|
||||
return tips;
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.batterytip.detectors;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.fuelgauge.BatteryInfo;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.DockDefenderTip;
|
||||
|
||||
/** Detect whether the dock defender mode is enabled. */
|
||||
public class DockDefenderDetector implements BatteryTipDetector {
|
||||
private final BatteryInfo mBatteryInfo;
|
||||
private final Context mContext;
|
||||
|
||||
public DockDefenderDetector(BatteryInfo batteryInfo, Context context) {
|
||||
mBatteryInfo = batteryInfo;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatteryTip detect() {
|
||||
int mode = BatteryUtils.getCurrentDockDefenderMode(mContext, mBatteryInfo);
|
||||
return new DockDefenderTip(
|
||||
mode != BatteryUtils.DockDefenderMode.DISABLED
|
||||
? BatteryTip.StateType.NEW
|
||||
: BatteryTip.StateType.INVISIBLE,
|
||||
mode);
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.batterytip.tips;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Parcel;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.BatteryUtils.DockDefenderMode;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.CardPreference;
|
||||
import com.android.settingslib.HelpUtils;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
/** Tip to show dock defender status */
|
||||
public class DockDefenderTip extends BatteryTip {
|
||||
private static final String TAG = "DockDefenderTip";
|
||||
private int mMode;
|
||||
|
||||
public DockDefenderTip(@StateType int state, @DockDefenderMode int mode) {
|
||||
super(TipType.DOCK_DEFENDER, state, false);
|
||||
mMode = mode;
|
||||
}
|
||||
|
||||
private DockDefenderTip(Parcel in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
public int getMode() {
|
||||
return mMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getTitle(Context context) {
|
||||
switch (mMode) {
|
||||
case DockDefenderMode.FUTURE_BYPASS:
|
||||
return context.getString(R.string.battery_tip_dock_defender_future_bypass_title);
|
||||
case DockDefenderMode.ACTIVE:
|
||||
return context.getString(R.string.battery_tip_dock_defender_active_title);
|
||||
case DockDefenderMode.TEMPORARILY_BYPASSED:
|
||||
return context.getString(
|
||||
R.string.battery_tip_dock_defender_temporarily_bypassed_title);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary(Context context) {
|
||||
switch (mMode) {
|
||||
case DockDefenderMode.FUTURE_BYPASS:
|
||||
return context.getString(R.string.battery_tip_dock_defender_future_bypass_summary);
|
||||
case DockDefenderMode.ACTIVE:
|
||||
return context.getString(R.string.battery_tip_dock_defender_active_summary);
|
||||
case DockDefenderMode.TEMPORARILY_BYPASSED:
|
||||
return context.getString(
|
||||
R.string.battery_tip_dock_defender_temporarily_bypassed_summary);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconId() {
|
||||
return mMode == DockDefenderMode.ACTIVE
|
||||
? R.drawable.ic_battery_status_protected_24dp
|
||||
: R.drawable.ic_battery_dock_defender_untriggered_24dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(BatteryTip tip) {
|
||||
mState = tip.mState;
|
||||
if (tip instanceof DockDefenderTip) {
|
||||
mMode = ((DockDefenderTip) tip).mMode;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
|
||||
metricsFeatureProvider.action(context, SettingsEnums.ACTION_DOCK_DEFENDER_TIP, mState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePreference(Preference preference) {
|
||||
super.updatePreference(preference);
|
||||
final Context context = preference.getContext();
|
||||
|
||||
CardPreference cardPreference = castToCardPreferenceSafely(preference);
|
||||
if (cardPreference == null) {
|
||||
Log.e(TAG, "cast Preference to CardPreference failed");
|
||||
return;
|
||||
}
|
||||
|
||||
cardPreference.setSelectable(false);
|
||||
switch (mMode) {
|
||||
case DockDefenderMode.FUTURE_BYPASS:
|
||||
case DockDefenderMode.ACTIVE:
|
||||
cardPreference.setPrimaryButtonText(
|
||||
context.getString(R.string.battery_tip_charge_to_full_button));
|
||||
cardPreference.setPrimaryButtonClickListener(
|
||||
unused -> {
|
||||
resumeCharging(context);
|
||||
mMode = DockDefenderMode.TEMPORARILY_BYPASSED;
|
||||
context.sendBroadcast(
|
||||
new Intent()
|
||||
.setAction(BatteryUtils.BYPASS_DOCK_DEFENDER_ACTION)
|
||||
.setPackage(context.getPackageName())
|
||||
.addFlags(
|
||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY
|
||||
| Intent.FLAG_RECEIVER_FOREGROUND));
|
||||
updatePreference(preference);
|
||||
});
|
||||
cardPreference.setPrimaryButtonVisible(true);
|
||||
break;
|
||||
case DockDefenderMode.TEMPORARILY_BYPASSED:
|
||||
cardPreference.setPrimaryButtonVisible(false);
|
||||
break;
|
||||
default:
|
||||
cardPreference.setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
cardPreference.setSecondaryButtonText(context.getString(R.string.learn_more));
|
||||
cardPreference.setSecondaryButtonClickListener(
|
||||
button ->
|
||||
button.startActivityForResult(
|
||||
HelpUtils.getHelpIntent(
|
||||
context,
|
||||
context.getString(R.string.help_url_dock_defender),
|
||||
/* backupContext */ ""), /* requestCode */
|
||||
0));
|
||||
cardPreference.setSecondaryButtonVisible(true);
|
||||
cardPreference.setSecondaryButtonContentDescription(
|
||||
context.getString(
|
||||
R.string.battery_tip_limited_temporarily_sec_button_content_description));
|
||||
}
|
||||
|
||||
private void resumeCharging(Context context) {
|
||||
final Intent intent =
|
||||
FeatureFactory.getFeatureFactory()
|
||||
.getPowerUsageFeatureProvider()
|
||||
.getResumeChargeIntent(true);
|
||||
if (intent != null) {
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
Log.i(TAG, "send resume charging broadcast intent=" + intent);
|
||||
}
|
||||
|
||||
public static final Creator CREATOR =
|
||||
new Creator() {
|
||||
public BatteryTip createFromParcel(Parcel in) {
|
||||
return new DockDefenderTip(in);
|
||||
}
|
||||
|
||||
public BatteryTip[] newArray(int size) {
|
||||
return new DockDefenderTip[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public final class IncompatibleChargerTip extends BatteryTip {
|
||||
|
||||
@Override
|
||||
public int getIconId() {
|
||||
return R.drawable.ic_battery_charger;
|
||||
return R.drawable.ic_battery_incompatible_charger;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -91,6 +91,10 @@ final class AnomalyEventWrapper {
|
||||
mRelatedBatteryDiffEntry = batteryDiffEntry;
|
||||
}
|
||||
|
||||
int getAnomalyKeyNumber() {
|
||||
return mPowerAnomalyEvent.getKey().getNumber();
|
||||
}
|
||||
|
||||
String getEventId() {
|
||||
return mPowerAnomalyEvent.hasEventId() ? mPowerAnomalyEvent.getEventId() : null;
|
||||
}
|
||||
|
||||
@@ -91,9 +91,11 @@ public class BatteryTipsController extends BasePreferenceController {
|
||||
}
|
||||
mCardPreference.setVisible(false);
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
|
||||
mAnomalyEventWrapper.getEventId());
|
||||
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
|
||||
/* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* key= */ mAnomalyEventWrapper.getEventId(),
|
||||
/* value= */ mAnomalyEventWrapper.getAnomalyKeyNumber());
|
||||
}
|
||||
|
||||
void handleBatteryTipsCardUpdated(
|
||||
@@ -105,8 +107,8 @@ public class BatteryTipsController extends BasePreferenceController {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get card preference strings and navigate fragment info
|
||||
final String eventId = mAnomalyEventWrapper.getEventId();
|
||||
final int anomalyKeyNumber = mAnomalyEventWrapper.getAnomalyKeyNumber();
|
||||
|
||||
// Update card & buttons preference
|
||||
if (!mAnomalyEventWrapper.updateTipsCardPreference(mCardPreference)) {
|
||||
@@ -122,7 +124,11 @@ public class BatteryTipsController extends BasePreferenceController {
|
||||
mOnAnomalyConfirmListener.onAnomalyConfirm();
|
||||
} else if (mAnomalyEventWrapper.launchSubSetting()) {
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, eventId);
|
||||
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
|
||||
/* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* key= */ eventId,
|
||||
/* value= */ anomalyKeyNumber);
|
||||
}
|
||||
});
|
||||
mCardPreference.setOnRejectListener(
|
||||
@@ -138,11 +144,19 @@ public class BatteryTipsController extends BasePreferenceController {
|
||||
DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, dismissRecordKey);
|
||||
}
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, eventId);
|
||||
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
|
||||
/* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* key= */ eventId,
|
||||
/* value= */ anomalyKeyNumber);
|
||||
});
|
||||
|
||||
mCardPreference.setVisible(true);
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, eventId);
|
||||
/* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
/* pageId= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
/* key= */ eventId,
|
||||
/* value= */ anomalyKeyNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,8 @@ public abstract class ActiveSubscriptionsListener
|
||||
*/
|
||||
public SubscriptionManager getSubscriptionManager() {
|
||||
if (mSubscriptionManager == null) {
|
||||
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
|
||||
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class)
|
||||
.createForAllUserProfiles();
|
||||
}
|
||||
return mSubscriptionManager;
|
||||
}
|
||||
|
||||
@@ -153,7 +153,8 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mPreferenceGroupKey = preferenceGroupKey;
|
||||
mStartOrder = startOrder;
|
||||
mTelephonyManager = context.getSystemService(TelephonyManager.class);
|
||||
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
|
||||
mSubscriptionManager = context.getSystemService(SubscriptionManager.class)
|
||||
.createForAllUserProfiles();
|
||||
mWifiManager = context.getSystemService(WifiManager.class);
|
||||
mSubscriptionPreferences = new ArrayMap<>();
|
||||
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
|
||||
|
||||
@@ -101,7 +101,7 @@ public class SwitchToEuiccSubscriptionSidecar extends EuiccOperationSidecar {
|
||||
}
|
||||
|
||||
SubscriptionManager subscriptionManager = getContext().getSystemService(
|
||||
SubscriptionManager.class);
|
||||
SubscriptionManager.class).createForAllUserProfiles();
|
||||
mActiveSubInfos = SubscriptionUtil.getActiveSubscriptions(subscriptionManager);
|
||||
|
||||
// To check whether the esim slot's port is active. If yes, skip setSlotMapping. If no,
|
||||
|
||||
@@ -92,7 +92,7 @@ public class SwitchToRemovableSlotSidecar extends EuiccOperationSidecar
|
||||
mPhysicalSlotId = physicalSlotId;
|
||||
mRemovedSubInfo = removedSubInfo;
|
||||
SubscriptionManager subscriptionManager =
|
||||
getContext().getSystemService(SubscriptionManager.class);
|
||||
getContext().getSystemService(SubscriptionManager.class).createForAllUserProfiles();
|
||||
if (!mTelephonyManager.isMultiSimEnabled()
|
||||
&& SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream().anyMatch(
|
||||
SubscriptionInfo::isEmbedded)) {
|
||||
|
||||
@@ -162,7 +162,7 @@ public class UiccSlotUtil {
|
||||
Log.d(TAG, "The SimSlotMapping: " + uiccSlotMappings);
|
||||
|
||||
SubscriptionManager subscriptionManager = context.getSystemService(
|
||||
SubscriptionManager.class);
|
||||
SubscriptionManager.class).createForAllUserProfiles();
|
||||
int excludedLogicalSlotIndex = getExcludedLogicalSlotIndex(uiccSlotMappings,
|
||||
SubscriptionUtil.getActiveSubscriptions(subscriptionManager), removedSubInfo,
|
||||
telMgr.isMultiSimEnabled());
|
||||
@@ -203,7 +203,7 @@ public class UiccSlotUtil {
|
||||
}
|
||||
|
||||
SubscriptionManager subscriptionManager = context.getSystemService(
|
||||
SubscriptionManager.class);
|
||||
SubscriptionManager.class).createForAllUserProfiles();
|
||||
int excludedLogicalSlotIndex = getExcludedLogicalSlotIndex(uiccSlotMappings,
|
||||
SubscriptionUtil.getActiveSubscriptions(subscriptionManager), removedSubInfo,
|
||||
telMgr.isMultiSimEnabled());
|
||||
@@ -222,7 +222,7 @@ public class UiccSlotUtil {
|
||||
List<UiccCardInfo> uiccCardInfos = telMgr.getUiccCardsInfo();
|
||||
ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
|
||||
SubscriptionManager subscriptionManager = context.getSystemService(
|
||||
SubscriptionManager.class);
|
||||
SubscriptionManager.class).createForAllUserProfiles();
|
||||
SubscriptionInfo subInfo = SubscriptionUtil.getSubById(subscriptionManager, subId);
|
||||
|
||||
// checking whether this is the removable esim. If it is, then return the removable slot id.
|
||||
|
||||
@@ -145,12 +145,7 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
|
||||
) {
|
||||
Column {
|
||||
if (apnData.validEnabled) {
|
||||
apnData = apnData.copy(
|
||||
networkType = ApnNetworkTypes.getNetworkType(
|
||||
networkTypeSelectedOptionsState
|
||||
)
|
||||
)
|
||||
valid = validateApnData(uriInit, apnData, context)
|
||||
valid = validateApnData(apnData, context)
|
||||
valid?.let {
|
||||
Text(
|
||||
text = it,
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.Telephony
|
||||
import android.telephony.TelephonyManager
|
||||
import android.util.Log
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.utils.ThreadUtils
|
||||
@@ -200,14 +199,21 @@ fun updateApnDataToDatabase(
|
||||
}
|
||||
}
|
||||
|
||||
fun isItemExist(uri: Uri, apnData: ApnData, context: Context): String? {
|
||||
val contentValueMap = apnData.getContentValueMap(context)
|
||||
contentValueMap.remove(Telephony.Carriers.CARRIER_ENABLED)
|
||||
fun isItemExist(apnData: ApnData, context: Context): String? {
|
||||
var contentValueMap = apnData.getContentValueMap(context)
|
||||
val removedList = arrayListOf(
|
||||
Telephony.Carriers.NAME, Telephony.Carriers.USER,
|
||||
Telephony.Carriers.SERVER, Telephony.Carriers.PASSWORD, Telephony.Carriers.AUTH_TYPE,
|
||||
Telephony.Carriers.TYPE, Telephony.Carriers.NETWORK_TYPE_BITMASK,
|
||||
Telephony.Carriers.CARRIER_ENABLED
|
||||
)
|
||||
contentValueMap =
|
||||
contentValueMap.filterNot { removedList.contains(it.key) } as MutableMap<String, Any>
|
||||
val list = contentValueMap.entries.toList()
|
||||
val selection = list.joinToString(" AND ") { "${it.key} = ?" }
|
||||
val selectionArgs: Array<String> = list.map { it.value.toString() }.toTypedArray()
|
||||
context.contentResolver.query(
|
||||
uri,
|
||||
Telephony.Carriers.CONTENT_URI,
|
||||
sProjection,
|
||||
selection /* selection */,
|
||||
selectionArgs /* selectionArgs */,
|
||||
|
||||
@@ -173,7 +173,7 @@ fun validateAndSaveApnData(
|
||||
context: Context,
|
||||
uriInit: Uri
|
||||
): String? {
|
||||
val errorMsg = validateApnData(uriInit, newApnData, context)
|
||||
val errorMsg = validateApnData(newApnData, context)
|
||||
if (errorMsg != null) {
|
||||
return errorMsg
|
||||
}
|
||||
@@ -194,7 +194,7 @@ fun validateAndSaveApnData(
|
||||
*
|
||||
* @return An error message if the apn data is invalid, otherwise return null.
|
||||
*/
|
||||
fun validateApnData(uri: Uri, apnData: ApnData, context: Context): String? {
|
||||
fun validateApnData(apnData: ApnData, context: Context): String? {
|
||||
var errorMsg: String?
|
||||
val name = apnData.name
|
||||
val apn = apnData.apn
|
||||
@@ -206,7 +206,7 @@ fun validateApnData(uri: Uri, apnData: ApnData, context: Context): String? {
|
||||
validateMMSC(true, apnData.mmsc, context)
|
||||
}
|
||||
if (errorMsg == null) {
|
||||
errorMsg = isItemExist(uri, apnData, context)
|
||||
errorMsg = isItemExist(apnData, context)
|
||||
}
|
||||
if (errorMsg == null) {
|
||||
errorMsg = validateAPNType(
|
||||
|
||||
@@ -146,7 +146,7 @@ public class SelectableSubscriptions implements Callable<List<SubscriptionAnnota
|
||||
}
|
||||
|
||||
protected SubscriptionManager getSubscriptionManager(Context context) {
|
||||
return context.getSystemService(SubscriptionManager.class);
|
||||
return context.getSystemService(SubscriptionManager.class).createForAllUserProfiles();
|
||||
}
|
||||
|
||||
protected List<SubscriptionInfo> getAvailableSubInfoList(Context context) {
|
||||
|
||||
@@ -357,7 +357,7 @@ public class MobileNetworkUtils {
|
||||
final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
|
||||
.createForSubscriptionId(subId);
|
||||
final SubscriptionManager subscriptionManager = context.getSystemService(
|
||||
SubscriptionManager.class);
|
||||
SubscriptionManager.class).createForAllUserProfiles();
|
||||
telephonyManager.setDataEnabled(enabled);
|
||||
|
||||
if (disableOtherSubscriptions) {
|
||||
@@ -666,39 +666,26 @@ public class MobileNetworkUtils {
|
||||
* 2. Similar design which aligned with operator name displayed in status bar
|
||||
*/
|
||||
public static CharSequence getCurrentCarrierNameForDisplay(Context context, int subId) {
|
||||
final SubscriptionManager sm = context.getSystemService(SubscriptionManager.class);
|
||||
if (sm != null) {
|
||||
final SubscriptionInfo subInfo = getSubscriptionInfo(sm, subId);
|
||||
if (subInfo != null) {
|
||||
return subInfo.getCarrierName();
|
||||
}
|
||||
final SubscriptionInfo subInfo = getSubscriptionInfo(context, subId);
|
||||
if (subInfo != null) {
|
||||
return subInfo.getCarrierName();
|
||||
}
|
||||
return getOperatorNameFromTelephonyManager(context);
|
||||
}
|
||||
|
||||
public static CharSequence getCurrentCarrierNameForDisplay(Context context) {
|
||||
final SubscriptionManager sm = context.getSystemService(SubscriptionManager.class);
|
||||
if (sm != null) {
|
||||
final int subId = sm.getDefaultSubscriptionId();
|
||||
final SubscriptionInfo subInfo = getSubscriptionInfo(sm, subId);
|
||||
if (subInfo != null) {
|
||||
return subInfo.getCarrierName();
|
||||
}
|
||||
final SubscriptionInfo subInfo = getSubscriptionInfo(context,
|
||||
SubscriptionManager.getDefaultSubscriptionId());
|
||||
if (subInfo != null) {
|
||||
return subInfo.getCarrierName();
|
||||
}
|
||||
return getOperatorNameFromTelephonyManager(context);
|
||||
}
|
||||
|
||||
private static SubscriptionInfo getSubscriptionInfo(SubscriptionManager subManager, int subId) {
|
||||
List<SubscriptionInfo> subInfos = subManager.getActiveSubscriptionInfoList();
|
||||
if (subInfos == null) {
|
||||
return null;
|
||||
}
|
||||
for (SubscriptionInfo subInfo : subInfos) {
|
||||
if (subInfo.getSubscriptionId() == subId) {
|
||||
return subInfo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
private static @Nullable SubscriptionInfo getSubscriptionInfo(Context context, int subId) {
|
||||
SubscriptionManager sm = context.getSystemService(SubscriptionManager.class);
|
||||
if (sm == null) return null;
|
||||
return sm.createForAllUserProfiles().getActiveSubscriptionInfo(subId);
|
||||
}
|
||||
|
||||
private static String getOperatorNameFromTelephonyManager(Context context) {
|
||||
@@ -712,7 +699,7 @@ public class MobileNetworkUtils {
|
||||
|
||||
private static int[] getActiveSubscriptionIdList(Context context) {
|
||||
final SubscriptionManager subscriptionManager = context.getSystemService(
|
||||
SubscriptionManager.class);
|
||||
SubscriptionManager.class).createForAllUserProfiles();
|
||||
final List<SubscriptionInfo> subInfoList =
|
||||
subscriptionManager.getActiveSubscriptionInfoList();
|
||||
if (subInfoList == null) {
|
||||
|
||||
@@ -79,7 +79,8 @@ public class NetworkProviderWifiCallingGroup extends
|
||||
String preferenceGroupKey) {
|
||||
super(context);
|
||||
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
|
||||
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
|
||||
mSubscriptionManager = context.getSystemService(SubscriptionManager.class)
|
||||
.createForAllUserProfiles();
|
||||
mPreferenceGroupKey = preferenceGroupKey;
|
||||
mWifiCallingForSubPreferences = new ArrayMap<>();
|
||||
setSubscriptionInfoList(context);
|
||||
|
||||
@@ -43,7 +43,8 @@ public class SubscriptionActionDialogActivity extends FragmentActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mSubscriptionManager = getSystemService(SubscriptionManager.class);
|
||||
mSubscriptionManager = getSystemService(SubscriptionManager.class)
|
||||
.createForAllUserProfiles();
|
||||
setProgressState(PROGRESS_IS_NOT_SHOWING);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.android.settings.network.apn.ApnEditPageProvider
|
||||
import com.android.settings.spa.about.AboutPhonePageProvider
|
||||
import com.android.settings.spa.app.AllAppListPageProvider
|
||||
import com.android.settings.spa.app.AppsMainPageProvider
|
||||
import com.android.settings.spa.app.battery.BatteryOptimizationModeAppListPageProvider
|
||||
import com.android.settings.spa.app.appcompat.UserAspectRatioAppsPageProvider
|
||||
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
|
||||
import com.android.settings.spa.app.appinfo.CloneAppInfoSettingsProvider
|
||||
@@ -116,6 +117,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
|
||||
StorageAppListPageProvider.Games,
|
||||
ApnEditPageProvider,
|
||||
SimOnboardingPageProvider,
|
||||
BatteryOptimizationModeAppListPageProvider,
|
||||
)
|
||||
|
||||
override val logger = if (FeatureFlagUtils.isEnabled(
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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.spa.app.battery
|
||||
|
||||
import android.app.AppOpsManager
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.os.Bundle
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.os.bundleOf
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Utils
|
||||
import com.android.settings.core.SubSettingLauncher
|
||||
import com.android.settings.fuelgauge.AdvancedPowerUsageDetail
|
||||
import com.android.settings.fuelgauge.BatteryOptimizeUtils
|
||||
import com.android.settings.spa.app.AppRecordWithSize
|
||||
import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
|
||||
import com.android.settings.spa.app.rememberResetAppDialogPresenter
|
||||
import com.android.settingslib.fuelgauge.PowerAllowlistBackend
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.common.createSettingsPage
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.framework.compose.rememberContext
|
||||
import com.android.settingslib.spa.framework.util.filterItem
|
||||
import com.android.settingslib.spa.framework.util.mapItem
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spa.widget.ui.SpinnerOption
|
||||
import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
|
||||
import com.android.settingslib.spaprivileged.model.app.AppListModel
|
||||
import com.android.settingslib.spaprivileged.model.app.installed
|
||||
import com.android.settingslib.spaprivileged.model.app.userHandle
|
||||
import com.android.settingslib.spaprivileged.template.app.AppList
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListInput
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListItem
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListPage
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
object BatteryOptimizationModeAppListPageProvider : SettingsPageProvider {
|
||||
override val name = "BatteryOptimizationModeAppList"
|
||||
private val owner = createSettingsPage()
|
||||
|
||||
@Composable
|
||||
override fun Page(arguments: Bundle?) {
|
||||
BatteryOptimizationModeAppList()
|
||||
}
|
||||
|
||||
fun buildInjectEntry() = SettingsEntryBuilder
|
||||
.createInject(owner)
|
||||
.setSearchDataFn { null }
|
||||
.setUiLayoutFn {
|
||||
Preference(object : PreferenceModel {
|
||||
override val title = stringResource(R.string.app_battery_usage_title)
|
||||
override val onClick = navigator(name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BatteryOptimizationModeAppList(
|
||||
appList: @Composable AppListInput<AppRecordWithSize>.() -> Unit = { AppList() },
|
||||
) {
|
||||
AppListPage(
|
||||
title = stringResource(R.string.app_battery_usage_title),
|
||||
listModel = rememberContext(::BatteryOptimizationModeAppListModel),
|
||||
appList = appList,
|
||||
)
|
||||
}
|
||||
|
||||
class BatteryOptimizationModeAppListModel(
|
||||
private val context: Context,
|
||||
) : AppListModel<AppRecordWithSize> {
|
||||
|
||||
override fun getSpinnerOptions(recordList: List<AppRecordWithSize>): List<SpinnerOption> =
|
||||
OptimizationModeSpinnerItem.entries.map {
|
||||
SpinnerOption(
|
||||
id = it.ordinal,
|
||||
text = context.getString(it.stringResId),
|
||||
)
|
||||
}
|
||||
|
||||
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
|
||||
appListFlow.mapItem(::AppRecordWithSize)
|
||||
|
||||
override fun filter(
|
||||
userIdFlow: Flow<Int>,
|
||||
option: Int,
|
||||
recordListFlow: Flow<List<AppRecordWithSize>>,
|
||||
): Flow<List<AppRecordWithSize>> {
|
||||
PowerAllowlistBackend.getInstance(context).refreshList()
|
||||
return recordListFlow.filterItem {
|
||||
val appOptimizationMode = BatteryOptimizeUtils(context, it.app.uid, it.app.packageName)
|
||||
.getAppOptimizationMode(/* refreshList */ false);
|
||||
when (OptimizationModeSpinnerItem.entries.getOrNull(option)) {
|
||||
OptimizationModeSpinnerItem.Restricted ->
|
||||
appOptimizationMode == BatteryOptimizeUtils.MODE_RESTRICTED
|
||||
OptimizationModeSpinnerItem.Optimized ->
|
||||
appOptimizationMode == BatteryOptimizeUtils.MODE_OPTIMIZED
|
||||
OptimizationModeSpinnerItem.Unrestricted ->
|
||||
appOptimizationMode == BatteryOptimizeUtils.MODE_UNRESTRICTED
|
||||
else -> (true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun getSummary(option: Int, record: AppRecordWithSize): () -> String = {
|
||||
var summary = String()
|
||||
val app = record.app
|
||||
when {
|
||||
!app.installed && !app.isArchived -> {
|
||||
summary += context.getString(R.string.not_installed)
|
||||
}
|
||||
|
||||
!app.enabled -> {
|
||||
summary += context.getString(com.android.settingslib.R.string.disabled)
|
||||
}
|
||||
}
|
||||
summary
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun AppListItemModel<AppRecordWithSize>.AppItem() {
|
||||
AppListItem(onClick = {
|
||||
val args = bundleOf(
|
||||
AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME to record.app.packageName,
|
||||
AdvancedPowerUsageDetail.EXTRA_POWER_USAGE_PERCENT to Utils.formatPercentage(0),
|
||||
AdvancedPowerUsageDetail.EXTRA_UID to record.app.uid,
|
||||
)
|
||||
SubSettingLauncher(context)
|
||||
.setDestination(AdvancedPowerUsageDetail::class.java.name)
|
||||
.setTitleRes(R.string.battery_details_title)
|
||||
.setArguments(args)
|
||||
.setUserHandle(record.app.userHandle)
|
||||
.setSourceMetricsCategory(AppInfoSettingsProvider.METRICS_CATEGORY)
|
||||
.launch()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private enum class OptimizationModeSpinnerItem(val stringResId: Int) {
|
||||
All(R.string.filter_all_apps),
|
||||
Restricted(R.string.filter_battery_restricted_title),
|
||||
Optimized(R.string.filter_battery_optimized_title),
|
||||
Unrestricted(R.string.filter_battery_unrestricted_title);
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import android.app.role.RoleManager
|
||||
import android.app.settings.SettingsEnums
|
||||
import android.companion.AssociationRequest
|
||||
import android.content.Context
|
||||
import com.android.media.flags.Flags;
|
||||
import com.android.settings.R
|
||||
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
|
||||
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionListModel
|
||||
@@ -48,8 +49,9 @@ class MediaRoutingControlAppsListModel(context: Context) : AppOpPermissionListMo
|
||||
}
|
||||
|
||||
override fun isChangeable(record: AppOpPermissionRecord): Boolean {
|
||||
return super.isChangeable(record) && (this.roleManager
|
||||
?.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH)
|
||||
return Flags.enablePrivilegedRoutingForMediaRoutingControl()
|
||||
&& super.isChangeable(record)
|
||||
&& (this.roleManager?.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH)
|
||||
?.contains(record.app.packageName) == true)
|
||||
}
|
||||
|
||||
|
||||
@@ -1390,7 +1390,11 @@ public class WifiConfigController2 implements TextWatcher,
|
||||
|
||||
@VisibleForTesting
|
||||
void setAnonymousIdVisible() {
|
||||
mView.findViewById(R.id.l_anonymous).setVisibility(View.VISIBLE);
|
||||
View view = mView.findViewById(R.id.l_anonymous);
|
||||
if (view.getVisibility() == View.VISIBLE) {
|
||||
return;
|
||||
}
|
||||
view.setVisibility(View.VISIBLE);
|
||||
mEapAnonymousView.setText(DEFAULT_ANONYMOUS_ID);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ public class BatteryTipLoaderTest {
|
||||
private static final int[] TIP_ORDER = {
|
||||
BatteryTip.TipType.LOW_BATTERY,
|
||||
BatteryTip.TipType.BATTERY_DEFENDER,
|
||||
BatteryTip.TipType.DOCK_DEFENDER,
|
||||
BatteryTip.TipType.INCOMPATIBLE_CHARGER,
|
||||
BatteryTip.TipType.HIGH_DEVICE_USAGE
|
||||
};
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.batterytip.detectors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.refEq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.BatteryManager;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.fuelgauge.BatteryInfo;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.DockDefenderTip;
|
||||
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.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class DockDefenderDetectorTest {
|
||||
|
||||
private BatteryInfo mBatteryInfo;
|
||||
private DockDefenderDetector mDockDefenderDetector;
|
||||
private Context mContext;
|
||||
private FakeFeatureFactory mFakeFeatureFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
mBatteryInfo = new BatteryInfo();
|
||||
mBatteryInfo.pluggedStatus = BatteryManager.BATTERY_PLUGGED_DOCK;
|
||||
mDockDefenderDetector = new DockDefenderDetector(mBatteryInfo, mContext);
|
||||
Intent intent =
|
||||
BatteryTestUtils.getCustomBatteryIntent(
|
||||
BatteryManager.BATTERY_PLUGGED_DOCK,
|
||||
50 /* level */,
|
||||
100 /* scale */,
|
||||
BatteryManager.BATTERY_STATUS_CHARGING);
|
||||
doReturn(intent)
|
||||
.when(mContext)
|
||||
.registerReceiver(eq(null), refEq(new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
|
||||
|
||||
Settings.Global.putInt(
|
||||
mContext.getContentResolver(),
|
||||
BatteryUtils.SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS,
|
||||
0);
|
||||
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetect_dockDefenderTemporarilyBypassed() {
|
||||
Settings.Global.putInt(
|
||||
mContext.getContentResolver(),
|
||||
BatteryUtils.SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS,
|
||||
1);
|
||||
|
||||
BatteryTip batteryTip = mDockDefenderDetector.detect();
|
||||
|
||||
assertTrue(batteryTip instanceof DockDefenderTip);
|
||||
assertEquals(
|
||||
((DockDefenderTip) batteryTip).getMode(),
|
||||
BatteryUtils.DockDefenderMode.TEMPORARILY_BYPASSED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetect_dockDefenderActive() {
|
||||
mBatteryInfo.isBatteryDefender = true;
|
||||
doReturn(true).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
|
||||
|
||||
BatteryTip batteryTip = mDockDefenderDetector.detect();
|
||||
|
||||
assertTrue(batteryTip instanceof DockDefenderTip);
|
||||
assertEquals(
|
||||
((DockDefenderTip) batteryTip).getMode(), BatteryUtils.DockDefenderMode.ACTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetect_dockDefenderFutureBypass() {
|
||||
mBatteryInfo.isBatteryDefender = false;
|
||||
doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
|
||||
|
||||
BatteryTip batteryTip = mDockDefenderDetector.detect();
|
||||
|
||||
assertTrue(batteryTip instanceof DockDefenderTip);
|
||||
assertEquals(
|
||||
((DockDefenderTip) batteryTip).getMode(),
|
||||
BatteryUtils.DockDefenderMode.FUTURE_BYPASS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetect_overheatedTrue_dockDefenderDisabled() {
|
||||
mBatteryInfo.isBatteryDefender = true;
|
||||
doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
|
||||
|
||||
BatteryTip batteryTip = mDockDefenderDetector.detect();
|
||||
|
||||
assertTrue(batteryTip instanceof DockDefenderTip);
|
||||
assertEquals(
|
||||
((DockDefenderTip) batteryTip).getMode(), BatteryUtils.DockDefenderMode.DISABLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetect_pluggedInAC_dockDefenderDisabled() {
|
||||
mBatteryInfo.pluggedStatus = BatteryManager.BATTERY_PLUGGED_AC;
|
||||
|
||||
BatteryTip batteryTip = mDockDefenderDetector.detect();
|
||||
|
||||
assertTrue(batteryTip instanceof DockDefenderTip);
|
||||
assertEquals(
|
||||
((DockDefenderTip) batteryTip).getMode(), BatteryUtils.DockDefenderMode.DISABLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetect_overheatedTrueAndDockDefenderNotTriggered_dockDefenderDisabled() {
|
||||
doReturn(false).when(mFakeFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
|
||||
mBatteryInfo.isBatteryDefender = true;
|
||||
|
||||
BatteryTip batteryTip = mDockDefenderDetector.detect();
|
||||
|
||||
assertTrue(batteryTip instanceof DockDefenderTip);
|
||||
assertEquals(
|
||||
((DockDefenderTip) batteryTip).getMode(), BatteryUtils.DockDefenderMode.DISABLED);
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.batterytip.tips;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.widget.CardPreference;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.shadows.ShadowLog;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class DockDefenderTipTest {
|
||||
private Context mContext;
|
||||
private DockDefenderTip mDockDefenderTipFutureBypass;
|
||||
private DockDefenderTip mDockDefenderTipActive;
|
||||
private DockDefenderTip mDockDefenderTipTemporarilyBypassed;
|
||||
private DockDefenderTip mDockDefenderTipDisabled;
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
|
||||
@Mock private Preference mPreference;
|
||||
@Mock private CardPreference mCardPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
|
||||
|
||||
mDockDefenderTipFutureBypass =
|
||||
new DockDefenderTip(
|
||||
BatteryTip.StateType.NEW, BatteryUtils.DockDefenderMode.FUTURE_BYPASS);
|
||||
mDockDefenderTipActive =
|
||||
new DockDefenderTip(BatteryTip.StateType.NEW, BatteryUtils.DockDefenderMode.ACTIVE);
|
||||
mDockDefenderTipTemporarilyBypassed =
|
||||
new DockDefenderTip(
|
||||
BatteryTip.StateType.NEW,
|
||||
BatteryUtils.DockDefenderMode.TEMPORARILY_BYPASSED);
|
||||
mDockDefenderTipDisabled =
|
||||
new DockDefenderTip(
|
||||
BatteryTip.StateType.INVISIBLE, BatteryUtils.DockDefenderMode.DISABLED);
|
||||
|
||||
doReturn(mContext).when(mPreference).getContext();
|
||||
doReturn(mContext).when(mCardPreference).getContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTitle() {
|
||||
assertThat(mDockDefenderTipFutureBypass.getTitle(mContext).toString())
|
||||
.isEqualTo(
|
||||
mContext.getString(R.string.battery_tip_dock_defender_future_bypass_title));
|
||||
assertThat(mDockDefenderTipActive.getTitle(mContext).toString())
|
||||
.isEqualTo(mContext.getString(R.string.battery_tip_dock_defender_active_title));
|
||||
assertThat(mDockDefenderTipTemporarilyBypassed.getTitle(mContext).toString())
|
||||
.isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.battery_tip_dock_defender_temporarily_bypassed_title));
|
||||
assertThat(mDockDefenderTipDisabled.getTitle(mContext)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSummary() {
|
||||
assertThat(mDockDefenderTipFutureBypass.getSummary(mContext).toString())
|
||||
.isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.battery_tip_dock_defender_future_bypass_summary));
|
||||
assertThat(mDockDefenderTipActive.getSummary(mContext).toString())
|
||||
.isEqualTo(mContext.getString(R.string.battery_tip_dock_defender_active_summary));
|
||||
assertThat(mDockDefenderTipTemporarilyBypassed.getSummary(mContext).toString())
|
||||
.isEqualTo(
|
||||
mContext.getString(
|
||||
R.string.battery_tip_dock_defender_temporarily_bypassed_summary));
|
||||
assertThat(mDockDefenderTipDisabled.getSummary(mContext)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIconId_dockDefenderActive_getProtectedIcon() {
|
||||
assertThat(mDockDefenderTipActive.getIconId())
|
||||
.isEqualTo(R.drawable.ic_battery_status_protected_24dp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIconId_dockDefenderNotActive_getUntriggeredIcon() {
|
||||
assertThat(mDockDefenderTipFutureBypass.getIconId())
|
||||
.isEqualTo(R.drawable.ic_battery_dock_defender_untriggered_24dp);
|
||||
assertThat(mDockDefenderTipTemporarilyBypassed.getIconId())
|
||||
.isEqualTo(R.drawable.ic_battery_dock_defender_untriggered_24dp);
|
||||
assertThat(mDockDefenderTipDisabled.getIconId())
|
||||
.isEqualTo(R.drawable.ic_battery_dock_defender_untriggered_24dp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState() {
|
||||
mDockDefenderTipTemporarilyBypassed.updateState(mDockDefenderTipDisabled);
|
||||
|
||||
assertThat(mDockDefenderTipTemporarilyBypassed.getState())
|
||||
.isEqualTo(BatteryTip.StateType.INVISIBLE);
|
||||
assertThat(mDockDefenderTipTemporarilyBypassed.getMode())
|
||||
.isEqualTo(BatteryUtils.DockDefenderMode.DISABLED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog() {
|
||||
mDockDefenderTipActive.log(mContext, mMetricsFeatureProvider);
|
||||
|
||||
verify(mMetricsFeatureProvider)
|
||||
.action(
|
||||
mContext,
|
||||
SettingsEnums.ACTION_DOCK_DEFENDER_TIP,
|
||||
mDockDefenderTipActive.getState());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdatePreference_dockDefenderTipFutureBypass() {
|
||||
mDockDefenderTipFutureBypass.updatePreference(mCardPreference);
|
||||
|
||||
verify(mCardPreference).setPrimaryButtonVisible(true);
|
||||
verify(mCardPreference)
|
||||
.setPrimaryButtonText(
|
||||
mContext.getString(R.string.battery_tip_charge_to_full_button));
|
||||
verifySecondaryButton();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdatePreference_dockDefenderTipActive() {
|
||||
mDockDefenderTipActive.updatePreference(mCardPreference);
|
||||
|
||||
verify(mCardPreference).setPrimaryButtonVisible(true);
|
||||
verify(mCardPreference)
|
||||
.setPrimaryButtonText(
|
||||
mContext.getString(R.string.battery_tip_charge_to_full_button));
|
||||
verifySecondaryButton();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdatePreference_dockDefenderTipTemporarilyBypassed() {
|
||||
mDockDefenderTipTemporarilyBypassed.updatePreference(mCardPreference);
|
||||
|
||||
verify(mCardPreference).setPrimaryButtonVisible(false);
|
||||
verify(mCardPreference, never()).setPrimaryButtonText(any());
|
||||
verifySecondaryButton();
|
||||
}
|
||||
|
||||
private void verifySecondaryButton() {
|
||||
verify(mCardPreference).setSecondaryButtonText(mContext.getString(R.string.learn_more));
|
||||
verify(mCardPreference).setSecondaryButtonVisible(true);
|
||||
final String expectedContent =
|
||||
mContext.getString(
|
||||
R.string.battery_tip_limited_temporarily_sec_button_content_description);
|
||||
verify(mCardPreference).setSecondaryButtonContentDescription(expectedContent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_castFail_logErrorMessage() {
|
||||
mDockDefenderTipActive.updatePreference(mPreference);
|
||||
|
||||
assertThat(getLastErrorLog()).isEqualTo("cast Preference to CardPreference failed");
|
||||
}
|
||||
|
||||
private String getLastErrorLog() {
|
||||
return ShadowLog.getLogsForTag(DockDefenderTip.class.getSimpleName()).stream()
|
||||
.filter(log -> log.type == Log.ERROR)
|
||||
.reduce((first, second) -> second)
|
||||
.orElse(createErrorLog("No Error Log"))
|
||||
.msg;
|
||||
}
|
||||
|
||||
private ShadowLog.LogItem createErrorLog(String msg) {
|
||||
return new ShadowLog.LogItem(Log.ERROR, "tag", msg, null);
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,8 @@ public final class IncompatibleChargerTipTest {
|
||||
|
||||
@Test
|
||||
public void getIcon_showIcon() {
|
||||
assertThat(mIncompatibleChargerTip.getIconId()).isEqualTo(R.drawable.ic_battery_charger);
|
||||
assertThat(mIncompatibleChargerTip.getIconId())
|
||||
.isEqualTo(R.drawable.ic_battery_incompatible_charger);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -120,12 +120,19 @@ public final class BatteryTipsCardPreferenceTest {
|
||||
assertThat(intent.getIntExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, -1))
|
||||
.isEqualTo(SettingsEnums.DISPLAY);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "BrightnessAnomaly");
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"BrightnessAnomaly",
|
||||
PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
mContext,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
|
||||
"BrightnessAnomaly");
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"BrightnessAnomaly",
|
||||
PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -146,14 +153,18 @@ public final class BatteryTipsCardPreferenceTest {
|
||||
.contains(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
mContext,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
"ScreenTimeoutAnomaly");
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"ScreenTimeoutAnomaly",
|
||||
PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
mContext,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
|
||||
"ScreenTimeoutAnomaly");
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"ScreenTimeoutAnomaly",
|
||||
PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
|
||||
}
|
||||
|
||||
@Ignore("b/313582999")
|
||||
@@ -173,9 +184,19 @@ public final class BatteryTipsCardPreferenceTest {
|
||||
verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
|
||||
verify(mBatteryChartPreferenceController).selectHighlightSlotIndex();
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "AppAnomaly");
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"AppAnomaly",
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, "AppAnomaly");
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"AppAnomaly",
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
}
|
||||
|
||||
@Ignore("b/313582999")
|
||||
@@ -194,8 +215,18 @@ public final class BatteryTipsCardPreferenceTest {
|
||||
verify(mBatteryChartPreferenceController).onHighlightSlotIndexUpdate(eq(1), eq(0));
|
||||
verify(mBatteryChartPreferenceController, never()).selectHighlightSlotIndex();
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "AppAnomaly");
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"AppAnomaly",
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, "AppAnomaly");
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"AppAnomaly",
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,12 @@ public final class BatteryTipsControllerTest {
|
||||
// Check proto info
|
||||
verify(mBatteryTipsCardPreference).setVisible(true);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "BrightnessAnomaly");
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"BrightnessAnomaly",
|
||||
PowerAnomalyKey.KEY_BRIGHTNESS.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -109,9 +114,11 @@ public final class BatteryTipsControllerTest {
|
||||
verify(mBatteryTipsCardPreference).setVisible(true);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
mContext,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
"ScreenTimeoutAnomaly");
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"ScreenTimeoutAnomaly",
|
||||
PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -138,9 +145,11 @@ public final class BatteryTipsControllerTest {
|
||||
verify(mBatteryTipsCardPreference).setVisible(true);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(
|
||||
mContext,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
"ScreenTimeoutAnomaly");
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"ScreenTimeoutAnomaly",
|
||||
PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -161,6 +170,11 @@ public final class BatteryTipsControllerTest {
|
||||
verify(mBatteryTipsCardPreference).setDismissButtonLabel("Got it");
|
||||
verify(mBatteryTipsCardPreference).setVisible(true);
|
||||
verify(mFeatureFactory.metricsFeatureProvider)
|
||||
.action(mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, "AppAnomaly");
|
||||
.action(
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW,
|
||||
SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL,
|
||||
"AppAnomaly",
|
||||
PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Implements(StorageManager.class)
|
||||
public class ShadowStorageManager {
|
||||
public class ShadowStorageManager extends org.robolectric.shadows.ShadowStorageManager {
|
||||
|
||||
private static boolean sIsUnmountCalled;
|
||||
private static boolean sIsForgetCalled;
|
||||
|
||||
@@ -21,9 +21,11 @@ import static com.android.settings.wifi.WifiConfigController2.WIFI_EAP_METHOD_SI
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -997,6 +999,18 @@ public class WifiConfigController2Test {
|
||||
assertThat(anonymousId.getText().toString()).isEqualTo(DEFAULT_ANONYMOUS_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAnonymousIdVisible_viewIsVisible_doNotSetText() {
|
||||
createController(mWifiEntry, WifiConfigUiBase2.MODE_CONNECT, false);
|
||||
View anonymousLayout = mView.findViewById(R.id.l_anonymous);
|
||||
mController.mEapAnonymousView = mock(TextView.class);
|
||||
anonymousLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
mController.setAnonymousIdVisible();
|
||||
|
||||
verify(mController.mEapAnonymousView, never()).setText(any(String.class));
|
||||
}
|
||||
|
||||
private void setUpModifyingSavedCertificateConfigController(String savedCaCertificate,
|
||||
String savedUserCertificate) {
|
||||
final WifiConfiguration mockWifiConfig = spy(new WifiConfiguration());
|
||||
|
||||
@@ -49,7 +49,8 @@ class OpenNetworkSelectPagePreferenceControllerTest {
|
||||
}
|
||||
|
||||
private val mockSubscriptionManager = mock<SubscriptionManager> {
|
||||
on { activeSubscriptionInfoList } doAnswer { listOf(subscriptionInfo) }
|
||||
on { createForAllUserProfiles() } doReturn mock
|
||||
on { getActiveSubscriptionInfo(SUB_ID) } doReturn subscriptionInfo
|
||||
}
|
||||
|
||||
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* 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.spa.app
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.DisplaySettings
|
||||
import com.android.settings.R
|
||||
import com.android.settings.SettingsActivity
|
||||
import com.android.settings.fuelgauge.AdvancedPowerUsageDetail
|
||||
import com.android.settings.spa.app.battery.BatteryOptimizationModeAppList
|
||||
import com.android.settings.spa.app.battery.BatteryOptimizationModeAppListModel
|
||||
import com.android.settings.spa.app.battery.BatteryOptimizationModeAppListPageProvider
|
||||
import com.android.settingslib.spa.testutils.FakeNavControllerWrapper
|
||||
import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
|
||||
import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListInput
|
||||
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.argumentCaptor
|
||||
import org.mockito.kotlin.doNothing
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.stub
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class BatteryOptimizationModeAppListPageProviderTest {
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
private val fakeNavControllerWrapper = FakeNavControllerWrapper()
|
||||
|
||||
private val packageManager = mock<PackageManager> {
|
||||
on { getPackagesForUid(USER_ID) } doReturn arrayOf(PACKAGE_NAME)
|
||||
}
|
||||
|
||||
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||
on { packageManager } doReturn packageManager
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryOptimizationModeAppListPageProvider_name() {
|
||||
assertThat(BatteryOptimizationModeAppListPageProvider.name)
|
||||
.isEqualTo("BatteryOptimizationModeAppList")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun injectEntry_title() {
|
||||
setInjectEntry()
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.app_battery_usage_title))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun injectEntry_onClick_navigate() {
|
||||
setInjectEntry()
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.app_battery_usage_title))
|
||||
.performClick()
|
||||
|
||||
assertThat(fakeNavControllerWrapper.navigateCalledWith)
|
||||
.isEqualTo("BatteryOptimizationModeAppList")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun title_displayed() {
|
||||
composeTestRule.setContent {
|
||||
BatteryOptimizationModeAppList {}
|
||||
}
|
||||
|
||||
composeTestRule.onNodeWithText(context.getString(R.string.app_battery_usage_title))
|
||||
.assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showInstantApps_isFalse() {
|
||||
val input = getAppListInput()
|
||||
|
||||
assertThat(input.config.showInstantApps).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun item_labelDisplayed() {
|
||||
setItemContent()
|
||||
|
||||
composeTestRule.onNodeWithText(LABEL).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun item_summaryDisplayed() {
|
||||
setItemContent()
|
||||
|
||||
composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun item_onClick_navigate() {
|
||||
setItemContent()
|
||||
doNothing().whenever(context).startActivity(any())
|
||||
|
||||
composeTestRule.onNodeWithText(LABEL).performClick()
|
||||
|
||||
val intent = argumentCaptor<Intent> {
|
||||
verify(context).startActivity(capture())
|
||||
}.firstValue
|
||||
|
||||
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))!!
|
||||
.isEqualTo(AdvancedPowerUsageDetail::class.java.name)
|
||||
val arguments = intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)!!
|
||||
assertThat(arguments.getString(AdvancedPowerUsageDetail.EXTRA_PACKAGE_NAME))
|
||||
.isEqualTo(PACKAGE_NAME)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun BatteryOptimizationModeAppListModel_transform() = runTest {
|
||||
val listModel = BatteryOptimizationModeAppListModel(context)
|
||||
|
||||
val recordListFlow = listModel.transform(flowOf(USER_ID), flowOf(listOf(APP)))
|
||||
|
||||
val recordList = recordListFlow.firstWithTimeoutOrNull()!!
|
||||
assertThat(recordList).hasSize(1)
|
||||
assertThat(recordList[0].app).isSameInstanceAs(APP)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun listModelGetSummary_regular() {
|
||||
val listModel = BatteryOptimizationModeAppListModel(context)
|
||||
|
||||
lateinit var summary: () -> String
|
||||
composeTestRule.setContent {
|
||||
summary = listModel.getSummary(option = 0, record = AppRecordWithSize(app = APP))
|
||||
}
|
||||
|
||||
assertThat(summary()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun listModelGetSummary_disabled() {
|
||||
val listModel = BatteryOptimizationModeAppListModel(context)
|
||||
val disabledApp = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
flags = ApplicationInfo.FLAG_INSTALLED
|
||||
enabled = false
|
||||
}
|
||||
|
||||
lateinit var summary: () -> String
|
||||
composeTestRule.setContent {
|
||||
summary =
|
||||
listModel.getSummary(option = 0, record = AppRecordWithSize(app = disabledApp))
|
||||
}
|
||||
|
||||
assertThat(summary())
|
||||
.isEqualTo(context.getString(com.android.settingslib.R.string.disabled))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun listModelGetSummary_notInstalled() {
|
||||
val listModel = BatteryOptimizationModeAppListModel(context)
|
||||
val notInstalledApp = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
}
|
||||
|
||||
lateinit var summary: () -> String
|
||||
composeTestRule.setContent {
|
||||
summary =
|
||||
listModel.getSummary(option = 0, record = AppRecordWithSize(app = notInstalledApp))
|
||||
}
|
||||
|
||||
assertThat(summary()).isEqualTo(context.getString(R.string.not_installed))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryOptimizationModeAppListModel_archivedApp() {
|
||||
val app = mock<ApplicationInfo> {
|
||||
on { loadUnbadgedIcon(any()) } doReturn UNBADGED_ICON
|
||||
on { loadLabel(any()) } doReturn LABEL
|
||||
}
|
||||
app.isArchived = true
|
||||
packageManager.stub {
|
||||
on {
|
||||
getApplicationInfoAsUser(PACKAGE_NAME, 0, USER_ID)
|
||||
} doReturn app
|
||||
}
|
||||
composeTestRule.setContent {
|
||||
fakeNavControllerWrapper.Wrapper {
|
||||
with(BatteryOptimizationModeAppListModel(context)) {
|
||||
AppListItemModel(
|
||||
record = AppRecordWithSize(app = app),
|
||||
label = LABEL,
|
||||
summary = { SUMMARY },
|
||||
).AppItem()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
composeTestRule.onNodeWithText(LABEL).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun batteryOptimizationModeAppListModel_NoStorageSummary() {
|
||||
val listModel = BatteryOptimizationModeAppListModel(context)
|
||||
val archivedApp = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
isArchived = true
|
||||
}
|
||||
|
||||
lateinit var summary: () -> String
|
||||
composeTestRule.setContent {
|
||||
summary =
|
||||
listModel.getSummary(option = 0, record = AppRecordWithSize(app = archivedApp))
|
||||
}
|
||||
|
||||
assertThat(summary()).isEmpty()
|
||||
}
|
||||
|
||||
private fun setInjectEntry() {
|
||||
composeTestRule.setContent {
|
||||
fakeNavControllerWrapper.Wrapper {
|
||||
BatteryOptimizationModeAppListPageProvider.buildInjectEntry().build().UiLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAppListInput(): AppListInput<AppRecordWithSize> {
|
||||
lateinit var input: AppListInput<AppRecordWithSize>
|
||||
composeTestRule.setContent {
|
||||
BatteryOptimizationModeAppList {
|
||||
SideEffect {
|
||||
input = this
|
||||
}
|
||||
}
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
||||
private fun setItemContent() {
|
||||
composeTestRule.setContent {
|
||||
fakeNavControllerWrapper.Wrapper {
|
||||
with(BatteryOptimizationModeAppListModel(context)) {
|
||||
AppListItemModel(
|
||||
record = AppRecordWithSize(app = APP),
|
||||
label = LABEL,
|
||||
summary = { SUMMARY },
|
||||
).AppItem()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val USER_ID = 0
|
||||
const val PACKAGE_NAME = "package.name"
|
||||
const val LABEL = "Label"
|
||||
const val SUMMARY = "Summary"
|
||||
val UNBADGED_ICON = mock<Drawable>()
|
||||
val APP = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
flags = ApplicationInfo.FLAG_INSTALLED
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,9 +23,11 @@ import android.app.settings.SettingsEnums
|
||||
import android.companion.AssociationRequest
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.platform.test.flag.junit.SetFlagsRule
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.media.flags.Flags
|
||||
import com.android.settings.R
|
||||
import com.android.settings.testutils.FakeFeatureFactory
|
||||
import com.android.settingslib.spaprivileged.model.app.IAppOpsController
|
||||
@@ -36,17 +38,19 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Spy
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.junit.MockitoRule
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.Mockito.verify
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MediaRoutingControlTest {
|
||||
@get:Rule
|
||||
val mockito: MockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@get:Rule val setFlagsRule: SetFlagsRule = SetFlagsRule();
|
||||
|
||||
@Spy
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
|
||||
@@ -143,6 +147,7 @@ class MediaRoutingControlTest {
|
||||
|
||||
@Test
|
||||
fun isChangeable_permissionRequestedByAppAndWatchCompanionRoleAssigned_shouldReturnTrue() {
|
||||
setFlagsRule.enableFlags(Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL)
|
||||
val permissionRequestedRecord =
|
||||
AppOpPermissionRecord(
|
||||
app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
|
||||
@@ -161,6 +166,7 @@ class MediaRoutingControlTest {
|
||||
|
||||
@Test
|
||||
fun isChangeable_permissionNotRequestedByAppButWatchCompanionRoleAssigned_shouldReturnFalse() {
|
||||
setFlagsRule.enableFlags(Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL)
|
||||
val permissionNotRequestedRecord =
|
||||
AppOpPermissionRecord(
|
||||
app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
|
||||
@@ -179,6 +185,7 @@ class MediaRoutingControlTest {
|
||||
|
||||
@Test
|
||||
fun isChangeable_permissionRequestedByAppButWatchCompanionRoleNotAssigned_shouldReturnFalse() {
|
||||
setFlagsRule.enableFlags(Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL)
|
||||
val permissionRequestedRecord =
|
||||
AppOpPermissionRecord(
|
||||
app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
|
||||
@@ -195,6 +202,25 @@ class MediaRoutingControlTest {
|
||||
assertThat(isSpecialAccessChangeable).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isChangeable_withFlagDisabled_shouldReturnFalse() {
|
||||
setFlagsRule.disableFlags(Flags.FLAG_ENABLE_PRIVILEGED_ROUTING_FOR_MEDIA_ROUTING_CONTROL)
|
||||
val permissionRequestedRecord =
|
||||
AppOpPermissionRecord(
|
||||
app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
|
||||
hasRequestPermission = true,
|
||||
hasRequestBroaderPermission = false,
|
||||
appOpsController =
|
||||
FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
|
||||
)
|
||||
whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH))
|
||||
.thenReturn(listOf(PACKAGE_NAME))
|
||||
|
||||
val isSpecialAccessChangeable = listModel.isChangeable(permissionRequestedRecord)
|
||||
|
||||
assertThat(isSpecialAccessChangeable).isFalse()
|
||||
}
|
||||
|
||||
private class FakeAppOpsController(fakeMode: Int) : IAppOpsController {
|
||||
|
||||
override val mode = MutableLiveData(fakeMode)
|
||||
|
||||
@@ -77,6 +77,7 @@ public class ActiveSubscriptionsListenerTest {
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
doReturn(mSubscriptionManager).when(mSubscriptionManager).createForAllUserProfiles();
|
||||
|
||||
mActiveSubscriptions = new ArrayList<SubscriptionInfo>();
|
||||
addMockSubscription(SUB_ID1);
|
||||
|
||||
@@ -77,6 +77,7 @@ public class UiccSlotUtilTest {
|
||||
when(mTelephonyManager.getUiccCardsInfo()).thenReturn(mUiccCardInfo);
|
||||
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager);
|
||||
when(mSubscriptionManager.getAllSubscriptionInfoList()).thenReturn(mSubscriptionInfoList);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ public class MobileNetworkUtilsTest {
|
||||
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager);
|
||||
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
|
||||
when(mTelephonyManager.createForSubscriptionId(SUB_ID_1)).thenReturn(mTelephonyManager);
|
||||
when(mTelephonyManager.createForSubscriptionId(SUB_ID_2)).thenReturn(mTelephonyManager2);
|
||||
|
||||
@@ -37,7 +37,6 @@ import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.FeatureFlagUtils;
|
||||
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceManager;
|
||||
@@ -100,6 +99,7 @@ public class NetworkProviderWifiCallingGroupTest {
|
||||
when(mContext.getSystemService(CarrierConfigManager.class)).thenReturn(
|
||||
mCarrierConfigManager);
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager);
|
||||
when(mContext.getSystemService(TelecomManager.class)).thenReturn(mTelecomManager);
|
||||
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
|
||||
when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
|
||||
|
||||
@@ -55,6 +55,7 @@ public class TelephonyBasePreferenceControllerTest {
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
when(mContext.getSystemService(SubscriptionManager.class))
|
||||
.thenReturn(mSubscriptionManager);
|
||||
when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager);
|
||||
when(mSubscriptionInfo.getSubscriptionId()).thenReturn(VALID_SUB_ID);
|
||||
mPreferenceController = new TestPreferenceController(mContext, "prefKey");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user