Snap for 7756953 from 8ab5c92adc to sc-v2-release

Change-Id: Ia01fa3410c2ad859ce73d1aaabcf42701ae4b6f6
This commit is contained in:
Android Build Coastguard Worker
2021-09-22 23:11:52 +00:00
29 changed files with 624 additions and 186 deletions

View File

@@ -2201,6 +2201,8 @@
<activity android:name=".development.AppPicker"
android:label="@string/select_application" />
<activity android:name=".development.AdbQrCodeActivity" />
<activity android:name=".development.DSULoader"
android:label="Select DSU Package"
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" />

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018 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.
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/ic_scan_32dp"
app:sudDescriptionText="@string/adb_wireless_qrcode_pairing_description">
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:id="@+id/camera_layout">
<FrameLayout
android:layout_width="@dimen/qrcode_preview_size"
android:layout_height="@dimen/qrcode_preview_size"
android:clipChildren="true">
<TextureView
android:id="@+id/preview_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</FrameLayout>
<TextView
android:id="@+id/error_message"
style="@style/TextAppearance.ErrorText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="?attr/sudMarginStart"
android:layout_marginEnd="?attr/sudMarginEnd"
android:textAlignment="center"
android:visibility="invisible"/>
</LinearLayout>
<!--
The spinner indicating that the device is waiting for pairing
after getting valid QR code
-->
<LinearLayout
android:id="@+id/verifying_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone">
<ProgressBar
android:id="@+id/verifying_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/verifying_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/adb_wireless_item_progress_text"
android:text="@string/adb_wireless_verifying_qrcode_text"
android:accessibilityLiveRegion="polite"/>
</LinearLayout>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -17,10 +17,11 @@
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/GlifV3Theme"
android:icon="@drawable/ic_scan_32dp">
android:icon="@drawable/ic_scan_32dp"
app:sudDescriptionText="@string/adb_wireless_qrcode_pairing_description">
<LinearLayout
style="@style/SudContentFrame"
@@ -32,52 +33,34 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:gravity="center_horizontal"
android:id="@+id/camera_layout">
<TextView
android:id="@android:id/summary"
style="@style/TextAppearance.SudGlifBody"
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="true">
<TextureView
android:id="@+id/preview_view"
android:layout_width="match_parent"
android:layout_height="@dimen/qrcode_preview_size"/>
<com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="match_parent"
android:layout_height="@dimen/qrcode_preview_size"/>
</FrameLayout>
<TextView
android:id="@+id/error_message"
style="@style/TextAppearance.ErrorText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="?attr/sudMarginStart"
android:layout_marginEnd="?attr/sudMarginEnd"
android:textAlignment="center"
android:accessibilityLiveRegion="polite"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clipChildren="true">
<TextureView
android:id="@+id/preview_view"
android:layout_width="match_parent"
android:layout_height="@dimen/qrcode_preview_size"/>
<com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="match_parent"
android:layout_height="@dimen/qrcode_preview_size"/>
</FrameLayout>
<TextView
android:id="@+id/error_message"
style="@style/TextAppearance.ErrorText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="?attr/sudMarginStart"
android:layout_marginEnd="?attr/sudMarginEnd"
android:textAlignment="center"
android:visibility="invisible"/>
</LinearLayout>
android:visibility="invisible"/>
</LinearLayout>
@@ -109,4 +92,5 @@
</LinearLayout>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -883,6 +883,9 @@
<!-- Note: Update FingerprintEnrollParentalConsent.CONSENT_STRING_RESOURCES when any _consent_ strings are added or removed. -->
<!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
<string name="security_settings_fingerprint_preference_title">Fingerprint</string>
<!-- Fingerprint enrollment and settings --><skip />
<!-- Title shown for work menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
<string name="security_settings_work_fingerprint_preference_title">Fingerprint for work</string>
<!-- Fingerprint managment category title - configuration options for managing enrolled fingerprints [CHAR LIMIT=22] -->
<string name="fingerprint_manage_category_title">Manage fingerprints</string>
<!-- Fingerprint category title - configuration options for managing fingerprint enrollment [CHAR LIMIT=22] -->

View File

@@ -155,7 +155,7 @@
<com.android.settingslib.RestrictedPreference
android:key="fingerprint_settings_profile"
android:title="@string/security_settings_fingerprint_preference_title"
android:title="@string/security_settings_work_fingerprint_preference_title"
android:summary="@string/summary_placeholder" />
<com.android.settingslib.RestrictedPreference

View File

@@ -18,6 +18,7 @@ package com.android.settings.biometrics.fingerprint;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
@@ -58,6 +59,8 @@ import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
@@ -69,11 +72,16 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
static final String TAG_SIDECAR = "sidecar";
private static final int PROGRESS_BAR_MAX = 10000;
private static final int FINISH_DELAY = 250;
/**
* Enroll with two center touches before going to guided enrollment.
*/
private static final int NUM_CENTER_TOUCHES = 2;
private static final int STAGE_UNKNOWN = -1;
private static final int STAGE_CENTER = 0;
private static final int STAGE_GUIDED = 1;
private static final int STAGE_FINGERTIP = 2;
private static final int STAGE_EDGES = 3;
@IntDef({STAGE_UNKNOWN, STAGE_CENTER, STAGE_GUIDED, STAGE_FINGERTIP, STAGE_EDGES})
@Retention(RetentionPolicy.SOURCE)
private @interface EnrollStage {}
/**
* If we don't see progress during this time, we show an error message to remind the users that
@@ -100,6 +108,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
private FingerprintManager mFingerprintManager;
private boolean mCanAssumeUdfps;
@Nullable private ProgressBar mProgressBar;
private ObjectAnimator mProgressAnim;
@@ -125,9 +134,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
mFingerprintManager = getSystemService(FingerprintManager.class);
final List<FingerprintSensorPropertiesInternal> props =
fingerprintManager.getSensorPropertiesInternal();
mFingerprintManager.getSensorPropertiesInternal();
mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType();
mAccessibilityManager = getSystemService(AccessibilityManager.class);
@@ -273,7 +282,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
// UDFPS animations are owned by SystemUI
if (progress >= PROGRESS_BAR_MAX) {
// Wait for any animations in SysUI to finish, then proceed to next page
getMainThreadHandler().postDelayed(mDelayedFinishRunnable, FINISH_DELAY);
getMainThreadHandler().postDelayed(mDelayedFinishRunnable, getFinishDelay());
}
return;
}
@@ -300,8 +309,55 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
private void updateTitleAndDescription() {
if (mCanAssumeUdfps) {
updateTitleAndDescriptionForUdfps();
return;
}
if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
if (mCanAssumeUdfps) {
setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message);
} else {
setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message);
}
}
private void updateTitleAndDescriptionForUdfps() {
switch (getCurrentStage()) {
case STAGE_CENTER:
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
setDescriptionText(R.string.security_settings_udfps_enroll_start_message);
break;
case STAGE_GUIDED:
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
if (mIsAccessibilityEnabled) {
setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message);
} else {
setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message);
}
break;
case STAGE_FINGERTIP:
setHeaderText(R.string.security_settings_udfps_enroll_fingertip_title);
if (isStageHalfCompleted()) {
setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_title);
} else {
setDescriptionText("");
}
break;
case STAGE_EDGES:
setHeaderText(R.string.security_settings_udfps_enroll_edge_title);
if (isStageHalfCompleted()) {
setDescriptionText(
R.string.security_settings_fingerprint_enroll_repeat_message);
} else {
setDescriptionText(R.string.security_settings_udfps_enroll_edge_message);
}
break;
case STAGE_UNKNOWN:
default:
// setHeaderText(R.string.security_settings_fingerprint_enroll_udfps_title);
// Don't use BiometricEnrollBase#setHeaderText, since that invokes setTitle,
// which gets announced for a11y upon entering the page. For UDFPS, we want to
@@ -309,41 +365,61 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
getLayout().setHeaderText(
R.string.security_settings_fingerprint_enroll_udfps_title);
setDescriptionText(R.string.security_settings_udfps_enroll_start_message);
final CharSequence description = getString(
R.string.security_settings_udfps_enroll_a11y);
getLayout().getHeaderTextView().setContentDescription(description);
setTitle(description);
} else {
setDescriptionText(R.string.security_settings_fingerprint_enroll_start_message);
}
} else if (mCanAssumeUdfps && !isCenterEnrollmentComplete()) {
if (mIsSetupWizard) {
setHeaderText(R.string.security_settings_udfps_enroll_title_one_more_time);
} else {
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
}
setDescriptionText(R.string.security_settings_udfps_enroll_start_message);
} else {
if (mCanAssumeUdfps) {
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
if (mIsAccessibilityEnabled) {
setDescriptionText(R.string.security_settings_udfps_enroll_repeat_a11y_message);
} else {
setDescriptionText(R.string.security_settings_udfps_enroll_repeat_message);
}
} else {
setDescriptionText(R.string.security_settings_fingerprint_enroll_repeat_message);
}
break;
}
}
private boolean isCenterEnrollmentComplete() {
@EnrollStage
private int getCurrentStage() {
if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
return STAGE_UNKNOWN;
}
final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining();
if (progressSteps < getStageThresholdSteps(0)) {
return STAGE_CENTER;
} else if (progressSteps < getStageThresholdSteps(1)) {
return STAGE_GUIDED;
} else if (progressSteps < getStageThresholdSteps(2)) {
return STAGE_FINGERTIP;
} else {
return STAGE_EDGES;
}
}
private boolean isStageHalfCompleted() {
// Prior to first enrollment step.
if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
return false;
}
final int stepsEnrolled = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining();
return stepsEnrolled >= NUM_CENTER_TOUCHES;
final int progressSteps = mSidecar.getEnrollmentSteps() - mSidecar.getEnrollmentRemaining();
int prevThresholdSteps = 0;
for (int i = 0; i < mFingerprintManager.getEnrollStageCount(); i++) {
final int thresholdSteps = getStageThresholdSteps(i);
if (progressSteps >= prevThresholdSteps && progressSteps < thresholdSteps) {
final int adjustedProgress = progressSteps - prevThresholdSteps;
final int adjustedThreshold = thresholdSteps - prevThresholdSteps;
return adjustedProgress >= adjustedThreshold / 2;
}
prevThresholdSteps = thresholdSteps;
}
// After last enrollment step.
return true;
}
private int getStageThresholdSteps(int index) {
if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
Log.w(TAG, "getStageThresholdSteps: Enrollment not started yet");
return 1;
}
return Math.round(mSidecar.getEnrollmentSteps()
* mFingerprintManager.getEnrollStageThreshold(index));
}
@Override
@@ -489,25 +565,29 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
mOrientationEventListener = null;
}
private final Animator.AnimatorListener mProgressAnimationListener
= new Animator.AnimatorListener() {
private final Animator.AnimatorListener mProgressAnimationListener =
new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) { }
@Override
public void onAnimationStart(Animator animation) { }
@Override
public void onAnimationRepeat(Animator animation) { }
@Override
public void onAnimationRepeat(Animator animation) { }
@Override
public void onAnimationEnd(Animator animation) {
if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) {
mProgressBar.postDelayed(mDelayedFinishRunnable, FINISH_DELAY);
}
}
@Override
public void onAnimationEnd(Animator animation) {
if (mProgressBar.getProgress() >= PROGRESS_BAR_MAX) {
mProgressBar.postDelayed(mDelayedFinishRunnable, getFinishDelay());
}
}
@Override
public void onAnimationCancel(Animator animation) { }
};
@Override
public void onAnimationCancel(Animator animation) { }
};
private long getFinishDelay() {
return mCanAssumeUdfps ? 400L : 250L;
}
// Give the user a chance to see progress completed before jumping to the next stage.
private final Runnable mDelayedFinishRunnable = new Runnable() {

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.development;
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.FragmentTransaction;
import com.android.settings.R;
import com.android.settings.wifi.dpp.WifiDppBaseActivity;
/**
* To scan an ADB QR code to pair a device.
*
* To use intent action {@code ACTION_ADB_QR_CODE_SCANNER}.
*/
public class AdbQrCodeActivity extends WifiDppBaseActivity {
private static final String TAG = "AdbQrCodeActivity";
static final String TAG_FRAGMENT_ADB_QR_CODE_SCANNER = "adb_qr_code_scanner_fragment";
public static final String ACTION_ADB_QR_CODE_SCANNER =
"android.settings.ADB_QR_CODE_SCANNER";
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_ADB_WIRELESS;
}
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
AdbQrcodeScannerFragment fragment =
(AdbQrcodeScannerFragment) mFragmentManager.findFragmentByTag(
TAG_FRAGMENT_ADB_QR_CODE_SCANNER);
if (fragment == null) {
fragment = new AdbQrcodeScannerFragment();
} else {
if (fragment.isVisible()) {
return;
}
// When the fragment in back stack but not on top of the stack, we can simply pop
// stack because current fragment transactions are arranged in an order
mFragmentManager.popBackStackImmediate();
return;
}
final FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment,
TAG_FRAGMENT_ADB_QR_CODE_SCANNER);
fragmentTransaction.commit();
}
@Override
protected void handleIntent(Intent intent) {
}
}

View File

@@ -16,8 +16,8 @@
package com.android.settings.development;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.debug.IAdbManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -28,7 +28,6 @@ import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
/**
* Controller for the "Pair device with QR code" preference in the Wireless debugging
@@ -68,12 +67,9 @@ public class AdbQrCodePreferenceController extends BasePreferenceController {
return false;
}
new SubSettingLauncher(preference.getContext())
.setDestination(AdbQrcodeScannerFragment.class.getName())
.setSourceMetricsCategory(SettingsEnums.SETTINGS_ADB_WIRELESS)
.setResultListener(mParentFragment,
WirelessDebuggingFragment.PAIRING_DEVICE_REQUEST)
.launch();
final Intent intent = new Intent(mContext, AdbQrCodeActivity.class);
mParentFragment.startActivityForResult(intent,
WirelessDebuggingFragment.PAIRING_DEVICE_REQUEST);
return true;
}
}

View File

@@ -44,12 +44,15 @@ import android.widget.TextView;
import androidx.annotation.StringRes;
import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.settings.wifi.dpp.AdbQrCode;
import com.android.settings.wifi.dpp.WifiDppQrCodeBaseFragment;
import com.android.settings.wifi.dpp.WifiNetworkConfig;
import com.android.settings.wifi.qrcode.QrCamera;
import com.android.settings.wifi.qrcode.QrDecorateView;
import com.google.android.setupdesign.util.ThemeHelper;
/**
* Fragment shown when clicking on the "Pair by QR code" preference in
* the Wireless Debugging fragment.
@@ -144,6 +147,9 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen
@Override
public void onCreate(Bundle savedInstanceState) {
Context context = getContext();
context.setTheme(SetupWizardUtils.getTheme(context, getActivity().getIntent()));
ThemeHelper.trySetDynamicColor(getContext());
super.onCreate(savedInstanceState);
mIntentFilter = new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
@@ -158,6 +164,7 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mSummary = view.findViewById(R.id.sud_layout_subtitle);
mTextureView = (TextureView) view.findViewById(R.id.preview_view);
mTextureView.setSurfaceTextureListener(this);
@@ -165,8 +172,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen
mDecorateView = view.findViewById(R.id.decorate_view);
setProgressBarShown(false);
setHeaderIconImageResource(R.drawable.ic_scan_24dp);
mQrCameraView = view.findViewById(R.id.camera_layout);
mVerifyingView = view.findViewById(R.id.verifying_layout);
mVerifyingTextView = view.findViewById(R.id.verifying_textview);
@@ -181,12 +186,18 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen
public void onResume() {
super.onResume();
restartCamera();
mAdbManager = IAdbManager.Stub.asInterface(ServiceManager.getService(Context.ADB_SERVICE));
getActivity().registerReceiver(mReceiver, mIntentFilter);
}
@Override
public void onPause() {
if (mCamera != null) {
mCamera.stop();
}
super.onPause();
getActivity().unregisterReceiver(mReceiver);
@@ -195,8 +206,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen
} catch (RemoteException e) {
Log.e(TAG, "Unable to cancel pairing");
}
getActivity().setResult(Activity.RESULT_CANCELED);
getActivity().finish();
}
@Override
@@ -213,7 +222,6 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().getActionBar().hide();
// setTitle for TalkBack
getActivity().setTitle(R.string.wifi_dpp_scan_qr_code);
}

View File

@@ -19,8 +19,8 @@ package com.android.settings.fuelgauge;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.settings.SettingsEnums;
import android.app.backup.BackupManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -361,18 +361,20 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
final String stateString;
final String footerString;
if (!mBatteryOptimizeUtils.isValidPackageName()) {
//Present optimized only string when the package name is invalid.
if (!mBatteryOptimizeUtils.isValidPackageName()
|| mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) {
// Present optimized only string when the package name is invalid or
// it's in allow list not idle app.
stateString = context.getString(R.string.manager_battery_usage_optimized_only);
footerString = context.getString(
R.string.manager_battery_usage_footer_limited, stateString);
} else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
//Present unrestricted only string when the package is system or default active app.
// Present unrestricted only string when the package is system or default active app.
stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
footerString = context.getString(
R.string.manager_battery_usage_footer_limited, stateString);
} else {
//Present default string to normal app.
// Present default string to normal app.
footerString = context.getString(R.string.manager_battery_usage_footer);
}
mFooterPreference.setTitle(footerString);

View File

@@ -130,6 +130,13 @@ public class BatteryOptimizeUtils {
|| mPowerAllowListBackend.isDefaultActiveApp(mPackageName);
}
/**
* Return {@code true} if this package is in allow list except idle app.
*/
public boolean isAllowlistedExceptIdleApp() {
return mPowerAllowListBackend.isAllowlistedExceptIdle(mPackageName);
}
String getPackageName() {
return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName;
}

View File

@@ -57,6 +57,10 @@ public class OptimizedPreferenceController extends AbstractPreferenceController
Log.d(TAG, "is system or default app, disable pref");
((RadioButtonPreference) preference).setChecked(false);
preference.setEnabled(false);
} else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) {
Log.d(TAG, "in allow list not idle app, optimized states only");
preference.setEnabled(true);
((RadioButtonPreference) preference).setChecked(true);
} else if (mBatteryOptimizeUtils.getAppOptimizationMode()
== BatteryOptimizeUtils.MODE_OPTIMIZED) {
Log.d(TAG, "is optimized states");

View File

@@ -55,6 +55,9 @@ public class RestrictedPreferenceController extends AbstractPreferenceController
Log.d(TAG, "is system or default app, disable pref");
((RadioButtonPreference) preference).setChecked(false);
preference.setEnabled(false);
} else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) {
Log.d(TAG, "in allow list not idle app, disable perf");
preference.setEnabled(false);
} else if (mBatteryOptimizeUtils.getAppOptimizationMode()
== BatteryOptimizeUtils.MODE_RESTRICTED) {
Log.d(TAG, "is restricted states");

View File

@@ -53,6 +53,9 @@ public class UnrestrictedPreferenceController extends AbstractPreferenceControll
if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
Log.d(TAG, "is system or default app, unrestricted states only");
((RadioButtonPreference) preference).setChecked(true);
} else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) {
Log.d(TAG, "in allow list not idle app, disable perf");
preference.setEnabled(false);
} else if (mBatteryOptimizeUtils.getAppOptimizationMode()
== BatteryOptimizeUtils.MODE_UNRESTRICTED) {
Log.d(TAG, "is unrestricted states");

View File

@@ -24,7 +24,6 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -40,6 +39,7 @@ import androidx.fragment.app.FragmentTransaction;
import androidx.window.embedding.SplitController;
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Utils;
import com.android.settings.accounts.AvatarViewMixin;
import com.android.settings.core.CategoryMixin;
@@ -180,12 +180,12 @@ public class SettingsHomepageActivity extends FragmentActivity implements
final Intent intent = getIntent();
if (intent == null || !TextUtils.equals(intent.getAction(),
Settings.ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK)) {
android.provider.Settings.ACTION_SETTINGS_LARGE_SCREEN_DEEP_LINK)) {
return;
}
final String intentUriString = intent.getStringExtra(
Settings.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI);
android.provider.Settings.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI);
if (TextUtils.isEmpty(intentUriString)) {
Log.e(TAG, "No EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_URI to deep link");
finish();
@@ -215,12 +215,17 @@ public class SettingsHomepageActivity extends FragmentActivity implements
targetIntent.putExtra(EXTRA_IS_FROM_SETTINGS_HOMEPAGE, true);
// Set 2-pane pair rule for the external deep link page.
// Set 2-pane pair rule for the deep link page.
ActivityEmbeddingRulesController.registerTwoPanePairRule(this,
new ComponentName(Utils.SETTINGS_PACKAGE_NAME, ALIAS_DEEP_LINK),
targetComponentName,
true /* finishPrimaryWithSecondary */,
true /* finishSecondaryWithPrimary */);
ActivityEmbeddingRulesController.registerTwoPanePairRule(this,
new ComponentName(Settings.class.getPackageName(), Settings.class.getName()),
targetComponentName,
true /* finishPrimaryWithSecondary */,
true /* finishSecondaryWithPrimary */);
startActivity(targetIntent);
}

View File

@@ -65,14 +65,12 @@ public class MobileNetworkListFragment extends DashboardFragment {
if (Utils.isProviderModelEnabled(getContext())) {
NetworkProviderSimsCategoryController simCategoryPrefCtrl =
new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM);
simCategoryPrefCtrl.init(getSettingsLifecycle());
new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM,
getSettingsLifecycle());
controllers.add(simCategoryPrefCtrl);
NetworkProviderDownloadedSimsCategoryController downloadedSimsCategoryCtrl =
new NetworkProviderDownloadedSimsCategoryController(context,
KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
downloadedSimsCategoryCtrl.init(getSettingsLifecycle());
KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM, getSettingsLifecycle());
controllers.add(downloadedSimsCategoryCtrl);
} else {
controllers.add(new MobileNetworkListController(getContext(), getLifecycle()));

View File

@@ -1,8 +1,8 @@
package com.android.settings.network;
import android.content.Context;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
@@ -15,23 +15,17 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
public class NetworkProviderDownloadedSimsCategoryController extends
PreferenceCategoryController implements LifecycleObserver {
private static final String LOG_TAG = "NetworkProviderDownloadedSimsCategoryController";
private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM =
"provider_model_downloaded_sim_category";
private PreferenceCategory mPreferenceCategory;
private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController;
public NetworkProviderDownloadedSimsCategoryController(Context context, String key) {
super(context, key);
}
public void init(Lifecycle lifecycle) {
mNetworkProviderDownloadedSimListController = createDownloadedSimListController(lifecycle);
}
@VisibleForTesting
protected NetworkProviderDownloadedSimListController createDownloadedSimListController(
public NetworkProviderDownloadedSimsCategoryController(Context context, String key,
Lifecycle lifecycle) {
return new NetworkProviderDownloadedSimListController(mContext, lifecycle);
super(context, key);
mNetworkProviderDownloadedSimListController =
new NetworkProviderDownloadedSimListController(mContext, lifecycle);
}
@Override
@@ -47,15 +41,23 @@ public class NetworkProviderDownloadedSimsCategoryController extends
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mNetworkProviderDownloadedSimListController.displayPreference(screen);
mPreferenceCategory = screen.findPreference(
KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
if (mPreferenceCategory == null) {
Log.d(LOG_TAG, "displayPreference(), Can not find the category.");
return;
}
mPreferenceCategory.setVisible(isAvailable());
mNetworkProviderDownloadedSimListController.displayPreference(screen);
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (mPreferenceCategory == null) {
Log.d(LOG_TAG, "updateState(), Can not find the category.");
return;
}
int count = mPreferenceCategory.getPreferenceCount();
String title = mContext.getString(count > 1
? R.string.downloaded_sims_category_title

View File

@@ -172,7 +172,6 @@ public class NetworkProviderSimListController extends AbstractPreferenceControll
for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
if (!info.isEmbedded()) {
subList.add(info);
break;
}
}
return subList;

View File

@@ -17,33 +17,28 @@
package com.android.settings.network;
import android.content.Context;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
public class NetworkProviderSimsCategoryController extends PreferenceCategoryController implements
LifecycleObserver {
private static final String LOG_TAG = "NetworkProviderSimsCategoryController";
private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category";
private NetworkProviderSimListController mNetworkProviderSimListController;
private PreferenceCategory mPreferenceCategory;
public NetworkProviderSimsCategoryController(Context context, String key) {
public NetworkProviderSimsCategoryController(Context context, String key, Lifecycle lifecycle) {
super(context, key);
}
public void init(Lifecycle lifecycle) {
mNetworkProviderSimListController = createSimListController(lifecycle);
}
@VisibleForTesting
protected NetworkProviderSimListController createSimListController(
Lifecycle lifecycle) {
return new NetworkProviderSimListController(mContext, lifecycle);
mNetworkProviderSimListController =
new NetworkProviderSimListController(mContext, lifecycle);
}
@Override
@@ -59,8 +54,26 @@ public class NetworkProviderSimsCategoryController extends PreferenceCategoryCon
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
PreferenceCategory preferenceCategory = screen.findPreference(KEY_PREFERENCE_CATEGORY_SIM);
preferenceCategory.setVisible(isAvailable());
mNetworkProviderSimListController.displayPreference(screen);
mPreferenceCategory = screen.findPreference(KEY_PREFERENCE_CATEGORY_SIM);
if (mPreferenceCategory == null) {
Log.d(LOG_TAG, "displayPreference(), Can not find the category.");
return;
}
mPreferenceCategory.setVisible(isAvailable());
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (mPreferenceCategory == null) {
Log.d(LOG_TAG, "updateState(), Can not find the category.");
return;
}
int count = mPreferenceCategory.getPreferenceCount();
String title = mContext.getString(count > 1
? R.string.provider_network_settings_title
: R.string.sim_category_title);
mPreferenceCategory.setTitle(title);
}
}

View File

@@ -484,7 +484,7 @@ public class WifiConfigController2 implements TextWatcher,
}
boolean isValidSaePassword(String password) {
if (password.length() >= 1 && password.length() <= 63) {
if (password.length() >= 1 && password.length() <= 128) {
return true;
}
return false;

View File

@@ -26,7 +26,7 @@ import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.settings.core.InstrumentedActivity;
abstract class WifiDppBaseActivity extends InstrumentedActivity {
public abstract class WifiDppBaseActivity extends InstrumentedActivity {
protected FragmentManager mFragmentManager;
protected abstract void handleIntent(Intent intent);

View File

@@ -745,6 +745,16 @@ public class AdvancedPowerUsageDetailTest {
.isEqualTo("This app requires optimized battery usage.");
}
@Test
public void testInitPreferenceForTriState_isAllowlistedExceptIdleApp_hasCorrectString() {
when(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true);
mFragment.initPreferenceForTriState(mContext);
assertThat(mFooterPreference.getTitle().toString())
.isEqualTo("This app requires optimized battery usage.");
}
@Test
public void testInitPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() {
when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);

View File

@@ -124,6 +124,18 @@ public class BatteryOptimizeUtilsTest {
assertThat(mBatteryOptimizeUtils.isValidPackageName()).isTrue();
}
@Test
public void testIsAllowlistedExpectIdle_isAllowlistedExceptIdle_returnTrue() {
when(mMockBackend.isAllowlistedExceptIdle(anyString())).thenReturn(true);
assertThat(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).isTrue();
}
@Test
public void testIsAllowlistedExpectIdle_notAllowlistedExpectIdle_returnFalse() {
assertThat(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).isFalse();
}
@Test
public void testSetAppOptimizationMode_Restricted_verifyAction() {
// Sets the current mode as MODE_UNRESTRICTED.

View File

@@ -93,6 +93,16 @@ public class OptimizedPreferenceControllerTest {
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void testUpdateState_isAllowlistedExceptIdleApp_prefEnabled() {
when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true);
mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isTrue();
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
mPreference.setKey(mController.KEY_OPTIMIZED_PREF);

View File

@@ -101,6 +101,16 @@ public class RestrictedPreferenceControllerTest {
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void testUpdateState_isAllowlistedExceptIdleApp_prefDisabled() {
when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
mPreference.setKey(mController.KEY_RESTRICTED_PREF);

View File

@@ -101,6 +101,16 @@ public class UnrestrictedPreferenceControllerTest {
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void testUpdateState_isAllowlistedExceptIdleApp_prefDisabled() {
when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
assertThat(mPreference.isEnabled()).isFalse();
}
@Test
public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
mPreference.setKey(mController.KEY_UNRESTRICTED_PREF);

View File

@@ -26,9 +26,12 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Looper;
import android.telephony.SubscriptionInfo;
import com.android.settings.testutils.ResourcesUtils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -41,38 +44,39 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
@RunWith(AndroidJUnit4.class)
public class NetworkProviderDownloadedSimsCategoryControllerTest {
private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM =
"provider_model_downloaded_sim_category";
private static final String KEY_ADD_MORE = "add_more";
private static final String SUB_1 = "SUB_1";
private static final String SUB_2 = "SUB_2";
private static final int SUB_ID_1 = 1;
private static final int SUB_ID_2 = 2;
@Mock
private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController;
@Mock
private PreferenceCategory mPreferenceCategory;
@Mock
private Lifecycle mLifecycle;
@Mock
private SubscriptionInfo mSubscriptionInfo1;
@Mock
private SubscriptionInfo mSubscriptionInfo2;
private Context mContext;
private NetworkProviderDownloadedSimsCategoryController mCategoryController;
private PreferenceCategory mPreferenceCategory;
private PreferenceManager mPreferenceManager;
private PreferenceScreen mPreferenceScreen;
private Preference mAddMorePreference;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
mCategoryController = new NetworkProviderDownloadedSimsCategoryController(
mContext, KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM) {
@Override
protected NetworkProviderDownloadedSimListController createDownloadedSimListController(
Lifecycle lifecycle) {
return mNetworkProviderDownloadedSimListController;
}
};
if (Looper.myLooper() == null) {
Looper.prepare();
@@ -80,14 +84,21 @@ public class NetworkProviderDownloadedSimsCategoryControllerTest {
mPreferenceManager = new PreferenceManager(mContext);
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
when(mPreferenceCategory.getKey()).thenReturn(KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
when(mPreferenceCategory.getPreferenceCount()).thenReturn(1);
mPreferenceCategory = new PreferenceCategory(mContext);
mPreferenceCategory.setKey(KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
mAddMorePreference = new Preference(mContext);
mAddMorePreference.setKey(KEY_ADD_MORE);
mAddMorePreference.setVisible(true);
mPreferenceScreen.addPreference(mPreferenceCategory);
mPreferenceScreen.addPreference(mAddMorePreference);
mCategoryController = new NetworkProviderDownloadedSimsCategoryController(mContext,
KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM, mLifecycle);
}
@Test
public void getAvailabilityStatus_returnUnavailable() {
mNetworkProviderDownloadedSimListController = null;
SubscriptionUtil.setAvailableSubscriptionsForTesting(new ArrayList<>());
assertThat(mCategoryController.getAvailabilityStatus()).isEqualTo(
CONDITIONALLY_UNAVAILABLE);
@@ -95,10 +106,46 @@ public class NetworkProviderDownloadedSimsCategoryControllerTest {
@Test
public void displayPreference_isVisible() {
when(mNetworkProviderDownloadedSimListController.isAvailable()).thenReturn(true);
mCategoryController.init(mLifecycle);
setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1));
mCategoryController.displayPreference(mPreferenceScreen);
assertEquals(mPreferenceCategory.isVisible(), true);
}
@Test
public void updateState_setTitle_withTwoDownloadedSims_returnDownloadedSims() {
setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
setUpSubscriptionInfoForDownloadedSim(SUB_ID_2, SUB_2, mSubscriptionInfo2);
SubscriptionUtil.setAvailableSubscriptionsForTesting(
Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2));
mCategoryController.displayPreference(mPreferenceScreen);
mCategoryController.updateState(mPreferenceCategory);
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2);
assertThat(mPreferenceCategory.getTitle()).isEqualTo(
ResourcesUtils.getResourcesString(mContext, "downloaded_sims_category_title"));
}
@Test
public void updateState_setTitle_withOneDownloadedSim_returnDownloadedSim() {
setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1));
mCategoryController.displayPreference(mPreferenceScreen);
mCategoryController.updateState(mPreferenceCategory);
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
assertThat(mPreferenceCategory.getTitle()).isEqualTo(
ResourcesUtils.getResourcesString(mContext, "downloaded_sim_category_title"));
}
private void setUpSubscriptionInfoForDownloadedSim(int subId, String displayName,
SubscriptionInfo subscriptionInfo) {
when(subscriptionInfo.isEmbedded()).thenReturn(true);
when(subscriptionInfo.getSubscriptionId()).thenReturn(subId);
when(subscriptionInfo.getDisplayName()).thenReturn(displayName);
}
}

View File

@@ -16,10 +16,14 @@
package com.android.settings.network;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static androidx.lifecycle.Lifecycle.Event;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -170,7 +174,6 @@ public class NetworkProviderSimListControllerTest {
assertTrue(TextUtils.equals(mController.getSummary(SUB_ID_1, DISPLAY_NAME_1), summary));
}
@Test
@UiThreadTest
public void getSummary_inactivePSim() {
@@ -227,4 +230,18 @@ public class NetworkProviderSimListControllerTest {
assertTrue(TextUtils.equals(mController.getSummary(SUB_ID_1, DISPLAY_NAME_1), summary));
}
@Test
@UiThreadTest
public void getAvailablePhysicalSubscription_withTwoPhysicalSims_returnTwo() {
final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
when(info1.isEmbedded()).thenReturn(false);
final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
when(info2.isEmbedded()).thenReturn(false);
when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
Arrays.asList(info1, info2));
displayPreferenceWithLifecycle();
assertThat(mController.getAvailablePhysicalSubscription().size()).isEqualTo(2);
}
}

View File

@@ -17,6 +17,7 @@
package com.android.settings.network;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -25,7 +26,10 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Looper;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import com.android.settings.testutils.ResourcesUtils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import androidx.preference.PreferenceCategory;
@@ -40,37 +44,35 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
@RunWith(AndroidJUnit4.class)
public class NetworkProviderSimsCategoryControllerTest {
private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category";
private static final String SUB_1 = "SUB_1";
private static final String SUB_2 = "SUB_2";
private static final int SUB_ID_1 = 1;
private static final int SUB_ID_2 = 2;
@Mock
private NetworkProviderSimListController mNetworkProviderSimListController;
@Mock
private PreferenceCategory mPreferenceCategory;
@Mock
private Lifecycle mLifecycle;
@Mock
private SubscriptionInfo mSubscriptionInfo1;
@Mock
private SubscriptionInfo mSubscriptionInfo2;
private Context mContext;
private NetworkProviderSimsCategoryController mCategoryController;
private PreferenceManager mPreferenceManager;
private PreferenceScreen mPreferenceScreen;
private PreferenceCategory mPreferenceCategory;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
mCategoryController = new NetworkProviderSimsCategoryController(
mContext, KEY_PREFERENCE_CATEGORY_SIM) {
@Override
protected NetworkProviderSimListController createSimListController(
Lifecycle lifecycle) {
return mNetworkProviderSimListController;
}
};
if (Looper.myLooper() == null) {
Looper.prepare();
@@ -78,14 +80,17 @@ public class NetworkProviderSimsCategoryControllerTest {
mPreferenceManager = new PreferenceManager(mContext);
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
when(mPreferenceCategory.getKey()).thenReturn(KEY_PREFERENCE_CATEGORY_SIM);
when(mPreferenceCategory.getPreferenceCount()).thenReturn(1);
mPreferenceCategory = new PreferenceCategory(mContext);
mPreferenceCategory.setKey(KEY_PREFERENCE_CATEGORY_SIM);
mPreferenceScreen.addPreference(mPreferenceCategory);
mCategoryController = new NetworkProviderSimsCategoryController(
mContext, KEY_PREFERENCE_CATEGORY_SIM, mLifecycle);
}
@Test
public void getAvailabilityStatus_returnUnavailable() {
mNetworkProviderSimListController = null;
SubscriptionUtil.setAvailableSubscriptionsForTesting(new ArrayList<>());
assertThat(mCategoryController.getAvailabilityStatus()).isEqualTo(
CONDITIONALLY_UNAVAILABLE);
@@ -93,10 +98,46 @@ public class NetworkProviderSimsCategoryControllerTest {
@Test
public void displayPreference_isVisible() {
when(mNetworkProviderSimListController.isAvailable()).thenReturn(true);
mCategoryController.init(mLifecycle);
setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1));
mCategoryController.displayPreference(mPreferenceScreen);
assertEquals(mPreferenceCategory.isVisible(), true);
}
@Test
public void updateState_setTitle_withTwoPhysicalSims_returnSims() {
setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
setUpSubscriptionInfoForPhysicalSim(SUB_ID_2, SUB_2, mSubscriptionInfo2);
SubscriptionUtil.setAvailableSubscriptionsForTesting(
Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2));
mCategoryController.displayPreference(mPreferenceScreen);
mCategoryController.updateState(mPreferenceCategory);
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2);
assertThat(mPreferenceCategory.getTitle()).isEqualTo(
ResourcesUtils.getResourcesString(mContext, "provider_network_settings_title"));
}
@Test
public void updateState_setTitle_withOnePhysicalSim_returnSim() {
setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1));
mCategoryController.displayPreference(mPreferenceScreen);
mCategoryController.updateState(mPreferenceCategory);
assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
assertThat(mPreferenceCategory.getTitle()).isEqualTo(
ResourcesUtils.getResourcesString(mContext, "sim_category_title"));
}
private void setUpSubscriptionInfoForPhysicalSim(int subId, String displayName,
SubscriptionInfo subscriptionInfo) {
when(subscriptionInfo.isEmbedded()).thenReturn(false);
when(subscriptionInfo.getSubscriptionId()).thenReturn(subId);
when(subscriptionInfo.getDisplayName()).thenReturn(displayName);
}
}