Snap for 11348195 from b6e28eeda5 to 24Q2-release

Change-Id: Idf38dabe0ac8c950dd3e05103f47694ff6eede76
This commit is contained in:
Android Build Coastguard Worker
2024-01-24 00:21:38 +00:00
47 changed files with 706 additions and 711 deletions

View File

@@ -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>

View 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>

View File

@@ -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>

View File

@@ -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"/>

View File

@@ -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) {

View File

@@ -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
}
}

View File

@@ -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"

View File

@@ -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);
}

View File

@@ -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) {}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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];
}
};
}

View File

@@ -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

View File

@@ -91,6 +91,10 @@ final class AnomalyEventWrapper {
mRelatedBatteryDiffEntry = batteryDiffEntry;
}
int getAnomalyKeyNumber() {
return mPowerAnomalyEvent.getKey().getNumber();
}
String getEventId() {
return mPowerAnomalyEvent.hasEventId() ? mPowerAnomalyEvent.getEventId() : null;
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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)) {

View File

@@ -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.

View File

@@ -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,

View File

@@ -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 */,

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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(

View File

@@ -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);
}

View File

@@ -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)
}

View File

@@ -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);
}

View File

@@ -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
};

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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;

View File

@@ -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());

View File

@@ -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()) {

View File

@@ -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
}
}
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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");
}