Merge "The page id SettingsEnums.DIALOG_PREFERRED_SIM_PICKER is duplicated"
diff --git a/res/layout/battery_usage_graph.xml b/res/layout/battery_usage_graph.xml
deleted file mode 100644
index e79c7b9..0000000
--- a/res/layout/battery_usage_graph.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="16dp"
- android:paddingStart="@dimen/preference_no_icon_padding_start"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/charge"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:fontFamily="@*android:string/config_headlineFontFamily"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="36sp"
- android:textColor="?android:attr/colorAccent" />
-
- <com.android.settings.widget.UsageView
- android:id="@+id/battery_usage"
- android:layout_width="match_parent"
- android:layout_height="141dp"
- android:layout_marginBottom="16dp"
- settings:sideLabels="@array/battery_labels"
- android:colorAccent="?android:attr/colorAccent"
- android:gravity="end"
- settings:textColor="?android:attr/textColorSecondary" />
-
- <TextView
- android:id="@+id/bottom_summary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="16dp"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
-</LinearLayout>
diff --git a/res/values/config.xml b/res/values/config.xml
index d7b2afa..e7efa6f 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -615,6 +615,9 @@
<item>android.uid.system:1000</item>
</string-array>
+ <!-- The default value for RedactionInterstitial in SUW -->
+ <bool name="default_allow_sensitive_lockscreen_content">true</bool>
+
<!-- Whether to enable the app battery usage list page feature. -->
<bool name="config_app_battery_usage_list_enabled">false</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 91587a9..2cfec6e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4582,8 +4582,6 @@
<string name="power_usage_summary_title">Battery</string>
<!-- Activity title summary for App Fuel Gauge summary -->
<string name="power_usage_summary">What has been using the battery</string>
- <!-- Message to show when battery usage data is not available [CHAR LIMIT=30] -->
- <string name="power_usage_not_available">Battery usage data isn\u2019t available.</string>
<!-- Display the battery level and status [CHAR_LIMIT=60] -->
<string name="power_usage_level_and_status"><xliff:g id="level">%1$s</xliff:g>
- <xliff:g id="status">%2$s</xliff:g></string>
@@ -4631,8 +4629,6 @@
<!-- Title for the screen usage in power use UI [CHAR_LIMIT=60] -->
<string name="device_screen_usage">Screen usage since full charge</string>
- <!-- Label for list of apps using battery in power use UI. Note: ^1 should be used in all translations[CHAR_LIMIT=120] -->
- <string name="power_usage_list_summary">Battery usage since full charge</string>
<!-- Temp string used to debug new battery estimates [DO NOT TRANSLATE] -->
<string name="power_usage_enhanced_debug" translatable="false"><xliff:g id="time">%1$s</xliff:g> left (New ML est)</string>
<!-- Temp string used to debug old battery estimates [DO NOT TRANSLATE] -->
@@ -4800,8 +4796,6 @@
<!-- Label for power consumed by Calling -->
<string name="power_phone">Voice calls</string>
- <!-- Description for battery usage time for an app, i.e. Used for 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
- <string name="battery_used_for">Used for <xliff:g id="time">^1</xliff:g></string>
<!-- Description for battery screen usage time for an app, i.e. Screen usage 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
<string name="battery_screen_usage">Screen usage <xliff:g id="time">^1</xliff:g></string>
<!-- Description for battery usage info for an app, i.e. 60% used by facebook. [CHAR LIMIT=60] -->
@@ -4870,9 +4864,6 @@
<!-- Description for other users aggregated battery usage data [CHAR LIMIT=120] -->
<string name="battery_usage_other_users">Other users</string>
- <!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] -->
- <string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string>
-
<!-- Description for battery time left, i.e. 50min Estimated time left. [CHAR LIMIT=80]-->
<string name="estimated_time_left">Estimated time left</string>
@@ -5141,6 +5132,8 @@
<string name="adaptive_connectivity_title">Adaptive connectivity</string>
<!-- Summary of Adaptive connectivity preference. [CHAR LIMIT=NONE] -->
<string name="adaptive_connectivity_summary">Extends battery life and improves device performance by automatically managing your network connections</string>
+ <!-- Title for adaptive connectivity main switch preferences. [CHAR LIMIT=50] -->
+ <string name="adaptive_connectivity_main_switch_title">Use adaptive connectivity</string>
<!-- Title of preference group for credential storage settings [CHAR LIMIT=30] -->
<string name="credentials_title">Credential storage</string>
@@ -10486,8 +10479,8 @@
<!-- Title for the button to reboot with MTE enabled. [CHAR LIMIT=NONE] -->
<string name="reboot_with_mte_title">Reboot with MTE</string>
<string name="reboot_with_mte_message">System will reboot and allow to experiment with Memory Tagging Extension (MTE). MTE may negatively impact system performance and stability. Will be reset on next subsequent reboot.</string>
- <string name="reboot_with_mte_summary">Try MTE for a single boot for app development.</string>
- <string name="reboot_with_mte_already_enabled">MTE is enabled through Advanced memory protection.</string>
+ <string name="reboot_with_mte_summary">Try MTE for a single boot for app development</string>
+ <string name="reboot_with_mte_already_enabled">MTE is enabled through Advanced memory protection</string>
<!-- Toast that is shown when the user initiates capturing a heap dump for the system server. [CHAR LIMIT=NONE] -->
<string name="capturing_system_heap_dump_message">Capturing system heap dump</string>
<!-- Toast that is shown if there's an error capturing the user initiated heap dump. [CHAR LIMIT=NONE] -->
diff --git a/res/xml/adaptive_connectivity_settings.xml b/res/xml/adaptive_connectivity_settings.xml
index d5941ad..6306006 100644
--- a/res/xml/adaptive_connectivity_settings.xml
+++ b/res/xml/adaptive_connectivity_settings.xml
@@ -30,7 +30,7 @@
<com.android.settingslib.widget.MainSwitchPreference
android:key="adaptive_connectivity"
- android:title="@string/adaptive_connectivity_title"
+ android:title="@string/adaptive_connectivity_main_switch_title"
settings:controller="com.android.settings.network.AdaptiveConnectivityTogglePreferenceController"/>
</PreferenceScreen>
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index 7635041..7fb818a 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -40,6 +40,9 @@
import android.widget.CheckBox;
import android.widget.Spinner;
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.VisibleForTesting;
import com.android.settings.core.InstrumentedFragment;
@@ -70,6 +73,7 @@
// Arbitrary to avoid conficts
private static final int KEYGUARD_REQUEST = 55;
+ private ActivityResultLauncher mActivityResultLauncher;
private List<SubscriptionInfo> mSubscriptions;
private View mContentView;
@@ -82,6 +86,10 @@
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.reset_network_title);
+
+ mActivityResultLauncher = registerForActivityResult(
+ new ActivityResultContracts.StartActivityForResult(),
+ result -> onActivityLauncherResult(result));
}
/**
@@ -96,20 +104,14 @@
new ChooseLockSettingsHelper.Builder(getActivity(), this);
return builder.setRequestCode(request)
.setTitle(res.getText(R.string.reset_network_title))
+ .setActivityResultLauncher(mActivityResultLauncher)
.show();
}
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- if (requestCode != KEYGUARD_REQUEST) {
- return;
- }
-
+ public void onActivityLauncherResult(ActivityResult result) {
// If the user entered a valid keyguard trace, present the final
// confirmation prompt; otherwise, go back to the initial state.
- if (resultCode == Activity.RESULT_OK) {
+ if (result.getResultCode() == Activity.RESULT_OK) {
showFinalConfirmation();
} else if (mContentView != null) {
establishInitialState(getActiveSubscriptionInfoList());
@@ -119,14 +121,28 @@
@VisibleForTesting
void showFinalConfirmation() {
Bundle args = new Bundle();
+
+ ResetNetworkRequest request = new ResetNetworkRequest(
+ ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER |
+ ResetNetworkRequest.RESET_VPN_MANAGER |
+ ResetNetworkRequest.RESET_WIFI_MANAGER |
+ ResetNetworkRequest.RESET_WIFI_P2P_MANAGER |
+ ResetNetworkRequest.RESET_BLUETOOTH_MANAGER
+ );
if (mSubscriptions != null && mSubscriptions.size() > 0) {
int selectedIndex = mSubscriptionSpinner.getSelectedItemPosition();
SubscriptionInfo subscription = mSubscriptions.get(selectedIndex);
- args.putInt(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
- subscription.getSubscriptionId());
+ int subId = subscription.getSubscriptionId();
+ request.setResetTelephonyAndNetworkPolicyManager(subId)
+ .setResetApn(subId);
}
- args.putBoolean(MainClear.ERASE_ESIMS_EXTRA,
- mEsimContainer.getVisibility() == View.VISIBLE && mEsimCheckbox.isChecked());
+ if (mEsimContainer.getVisibility() == View.VISIBLE && mEsimCheckbox.isChecked()) {
+ request.setResetEsim(getContext().getPackageName())
+ .writeIntoBundle(args);
+ } else {
+ request.writeIntoBundle(args);
+ }
+
new SubSettingLauncher(getContext())
.setDestination(ResetNetworkConfirm.class.getName())
.setArguments(args)
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index 52eb643..0cd94a5 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -56,10 +56,9 @@
private static final String TAG = "ResetNetworkConfirm";
@VisibleForTesting View mContentView;
- @VisibleForTesting boolean mEraseEsim;
@VisibleForTesting ResetNetworkTask mResetNetworkTask;
@VisibleForTesting Activity mActivity;
- private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ @VisibleForTesting ResetNetworkRequest mResetNetworkRequest;
private ProgressDialog mProgressDialog;
private AlertDialog mAlertDialog;
private OnSubscriptionsChangedListener mSubscriptionsChangedListener;
@@ -72,32 +71,25 @@
private static final String TAG = "ResetNetworkTask";
private final Context mContext;
- private final String mPackageName;
ResetNetworkTask(Context context) {
mContext = context;
- mPackageName = context.getPackageName();
}
@Override
protected Boolean doInBackground(Void... params) {
final AtomicBoolean resetEsimSuccess = new AtomicBoolean(true);
- ResetNetworkOperationBuilder builder =
- (new ResetNetworkOperationBuilder(mContext))
- .resetConnectivityManager()
- .resetVpnManager()
- .resetWifiManager()
- .resetWifiP2pManager(Looper.getMainLooper());
- if (mEraseEsim) {
- builder = builder.resetEsim(mContext.getPackageName(),
+
+ String resetEsimPackageName = mResetNetworkRequest.getResetEsimPackageName();
+ ResetNetworkOperationBuilder builder = mResetNetworkRequest
+ .toResetNetworkOperationBuilder(mContext, Looper.getMainLooper());
+ if (resetEsimPackageName != null) {
+ // Override reset eSIM option for the result of reset operation
+ builder = builder.resetEsim(resetEsimPackageName,
success -> { resetEsimSuccess.set(success); }
);
}
- builder.resetTelephonyAndNetworkPolicyManager(mSubId)
- .resetBluetoothManager()
- .resetApn(mSubId)
- .build()
- .run();
+ builder.build().run();
boolean isResetSucceed = resetEsimSuccess.get();
Log.d(TAG, "network factoryReset complete. succeeded: "
@@ -138,12 +130,13 @@
}
// abandon execution if subscription no longer active
- if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ int subId = mResetNetworkRequest.getResetApnSubId();
+ if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
SubscriptionManager mgr = getSubscriptionManager();
// always remove listener
stopMonitorSubscriptionChange(mgr);
- if (!isSubscriptionRemainActive(mgr, mSubId)) {
- Log.w(TAG, "subId " + mSubId + " disappear when confirm");
+ if (!isSubscriptionRemainActive(mgr, subId)) {
+ Log.w(TAG, "subId " + subId + " disappear when confirm");
mActivity.finish();
return;
}
@@ -182,7 +175,7 @@
@VisibleForTesting
void setSubtitle() {
- if (mEraseEsim) {
+ if (mResetNetworkRequest.getResetEsimPackageName() != null) {
((TextView) mContentView.findViewById(R.id.reset_network_confirm))
.setText(R.string.reset_network_final_desc_esim);
}
@@ -193,6 +186,7 @@
Bundle savedInstanceState) {
View view = (new ResetNetworkRestrictionViewBuilder(mActivity)).build();
if (view != null) {
+ stopMonitorSubscriptionChange(getSubscriptionManager());
Log.w(TAG, "Access deny.");
return view;
}
@@ -207,15 +201,15 @@
super.onCreate(savedInstanceState);
Bundle args = getArguments();
- if (args != null) {
- mSubId = args.getInt(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- mEraseEsim = args.getBoolean(MainClear.ERASE_ESIMS_EXTRA);
+ if (args == null) {
+ args = savedInstanceState;
}
+ mResetNetworkRequest = new ResetNetworkRequest(args);
mActivity = getActivity();
- if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ if (mResetNetworkRequest.getResetApnSubId()
+ == ResetNetworkRequest.INVALID_SUBSCRIPTION_ID) {
return;
}
// close confirmation dialog when reset specific subscription
@@ -223,6 +217,12 @@
startMonitorSubscriptionChange(getSubscriptionManager());
}
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mResetNetworkRequest.writeIntoBundle(outState);
+ }
+
private SubscriptionManager getSubscriptionManager() {
SubscriptionManager mgr = mActivity.getSystemService(SubscriptionManager.class);
if (mgr == null) {
@@ -240,12 +240,13 @@
Looper.getMainLooper()) {
@Override
public void onSubscriptionsChanged() {
+ int subId = mResetNetworkRequest.getResetApnSubId();
SubscriptionManager mgr = getSubscriptionManager();
- if (isSubscriptionRemainActive(mgr, mSubId)) {
+ if (isSubscriptionRemainActive(mgr, subId)) {
return;
}
// close UI if subscription no longer active
- Log.w(TAG, "subId " + mSubId + " no longer active.");
+ Log.w(TAG, "subId " + subId + " no longer active.");
stopMonitorSubscriptionChange(mgr);
mActivity.finish();
}
diff --git a/src/com/android/settings/ResetNetworkRequest.java b/src/com/android/settings/ResetNetworkRequest.java
new file mode 100644
index 0000000..40eebb0
--- /dev/null
+++ b/src/com/android/settings/ResetNetworkRequest.java
@@ -0,0 +1,224 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Looper;
+import android.telephony.SubscriptionManager;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.network.ResetNetworkOperationBuilder;
+
+/**
+ * A request which contains options required for resetting network.
+ */
+public class ResetNetworkRequest {
+
+ /* Reset option - nothing get reset */
+ public static final int RESET_NONE = 0x00;
+
+ /* Reset option - reset ConnectivityManager */
+ public static final int RESET_CONNECTIVITY_MANAGER = 0x01;
+
+ /* Reset option - reset VpnManager */
+ public static final int RESET_VPN_MANAGER = 0x02;
+
+ /* Reset option - reset WiFiManager */
+ public static final int RESET_WIFI_MANAGER = 0x04;
+
+ /* Reset option - reset WifiP2pManager */
+ public static final int RESET_WIFI_P2P_MANAGER = 0x08;
+
+ /* Reset option - reset BluetoothManager */
+ public static final int RESET_BLUETOOTH_MANAGER = 0x10;
+
+ /* Subscription ID for not performing reset TelephonyAndNetworkPolicy or reset APN */
+ public static final int INVALID_SUBSCRIPTION_ID = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+ /* Subscription ID for performing reset TelephonyAndNetworkPolicy or reset APN
+ on all subscriptions */
+ public static final int ALL_SUBSCRIPTION_ID = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+
+ /* Key within Bundle. To store some connectivity options for reset */
+ @VisibleForTesting
+ protected static final String KEY_RESET_OPTIONS = "resetNetworkOptions";
+
+ /* Key within Bundle. To store package name for resetting eSIM */
+ @VisibleForTesting
+ protected static final String KEY_ESIM_PACKAGE = "resetEsimPackage";
+
+ /**
+ * Key within Bundle. To store subscription ID for resetting
+ * telephony manager and network and network policy manager.
+ */
+ @VisibleForTesting
+ protected static final String KEY_TELEPHONY_NET_POLICY_MANAGER_SUBID =
+ "resetTelephonyNetPolicySubId";
+
+ /* Key within Bundle. To store subscription ID for resetting APN. */
+ @VisibleForTesting
+ protected static final String KEY_APN_SUBID = "resetApnSubId";
+
+ private int mResetOptions = RESET_NONE;
+ private String mResetEsimPackageName;
+ private int mResetTelephonyManager = INVALID_SUBSCRIPTION_ID;
+ private int mResetApn = INVALID_SUBSCRIPTION_ID;
+
+ /**
+ * Reconstruct based on keys stored within Bundle.
+ * @param optionsFromBundle is a Bundle which previously stored through #writeIntoBundle()
+ */
+ public ResetNetworkRequest(Bundle optionsFromBundle) {
+ if (optionsFromBundle == null) {
+ return;
+ }
+ mResetOptions = optionsFromBundle.getInt(KEY_RESET_OPTIONS, RESET_NONE);
+ mResetEsimPackageName = optionsFromBundle.getString(KEY_ESIM_PACKAGE);
+ mResetTelephonyManager = optionsFromBundle.getInt(
+ KEY_TELEPHONY_NET_POLICY_MANAGER_SUBID, INVALID_SUBSCRIPTION_ID);
+ mResetApn = optionsFromBundle.getInt(KEY_APN_SUBID, INVALID_SUBSCRIPTION_ID);
+ }
+
+ /**
+ * Construct of class
+ * @param resetOptions is a binary combination(OR logic operation) of constants
+ * comes with RESET_ prefix. Which are the reset options comes within.
+ */
+ public ResetNetworkRequest(int resetOptions) {
+ mResetOptions = resetOptions;
+ }
+
+ /**
+ * Get the package name applied for resetting eSIM.
+ * @return package name. {@code null} means resetting eSIM is not part of the
+ * option within this request.
+ */
+ public String getResetEsimPackageName() {
+ return mResetEsimPackageName;
+ }
+
+ /**
+ * Set the package name for resetting eSIM.
+ * @param packageName is the package name for resetting eSIM.
+ * {@code null} will remove the resetting eSIM option out of this request.
+ * @return this request
+ */
+ public ResetNetworkRequest setResetEsim(String packageName) {
+ mResetEsimPackageName = packageName;
+ return this;
+ }
+
+ /**
+ * Get the subscription ID applied for resetting Telephony and NetworkPolicy.
+ * @return subscription ID.
+ * {@code ALL_SUBSCRIPTION_ID} for applying to all subscriptions.
+ * {@code INVALID_SUBSCRIPTION_ID} means
+ * resetting Telephony and NetworkPolicy is not part of the option
+ * within this request.
+ */
+ public int getResetTelephonyAndNetworkPolicyManager() {
+ return mResetTelephonyManager;
+ }
+
+ /**
+ * Set the subscription ID applied for resetting Telephony and NetworkPolicy.
+ * @param subscriptionId is the subscription ID referenced fron SubscriptionManager.
+ * {@code ALL_SUBSCRIPTION_ID} for applying to all subscriptions.
+ * {@code INVALID_SUBSCRIPTION_ID} means resetting Telephony and NetworkPolicy
+ * will not take place.
+ * @return this request
+ */
+ public ResetNetworkRequest setResetTelephonyAndNetworkPolicyManager(int subscriptionId) {
+ mResetTelephonyManager = subscriptionId;
+ return this;
+ }
+
+ /**
+ * Get the subscription ID applied for resetting APN.
+ * @return subscription ID.
+ * {@code ALL_SUBSCRIPTION_ID} for applying to all subscriptions.
+ * {@code INVALID_SUBSCRIPTION_ID} means resetting APN
+ * is not part of the option within this request.
+ */
+ public int getResetApnSubId() {
+ return mResetApn;
+ }
+
+ /**
+ * Set the subscription ID applied for resetting APN.
+ * @param subscriptionId is the subscription ID referenced fron SubscriptionManager.
+ * {@code ALL_SUBSCRIPTION_ID} for applying to all subscriptions.
+ * {@code INVALID_SUBSCRIPTION_ID} means resetting APN will not take place.
+ * @return this request
+ */
+ public ResetNetworkRequest setResetApn(int subscriptionId) {
+ mResetApn = subscriptionId;
+ return this;
+ }
+
+ /**
+ * Store a copy of this request into Bundle given.
+ * @param writeToBundle is a Bundle for storing configurations of this request.
+ * @return this request
+ */
+ public ResetNetworkRequest writeIntoBundle(Bundle writeToBundle) {
+ writeToBundle.putInt(KEY_RESET_OPTIONS, mResetOptions);
+ writeToBundle.putString(KEY_ESIM_PACKAGE, mResetEsimPackageName);
+ writeToBundle.putInt(KEY_TELEPHONY_NET_POLICY_MANAGER_SUBID, mResetTelephonyManager);
+ writeToBundle.putInt(KEY_APN_SUBID, mResetApn);
+ return this;
+ }
+
+ /**
+ * Build a ResetNetworkOperationBuilder based on configurations within this request.
+ * @param context required by ResetNetworkOperationBuilder
+ * @param looper required by ResetNetworkOperationBuilder for callback support
+ * @return a ResetNetworkOperationBuilder
+ */
+ public ResetNetworkOperationBuilder toResetNetworkOperationBuilder(Context context,
+ Looper looper) {
+ // Follow specific order based on previous design within file ResetNetworkConfirm.java
+ ResetNetworkOperationBuilder builder = new ResetNetworkOperationBuilder(context);
+ if ((mResetOptions & RESET_CONNECTIVITY_MANAGER) != 0) {
+ builder.resetConnectivityManager();
+ }
+ if ((mResetOptions & RESET_VPN_MANAGER) != 0) {
+ builder.resetVpnManager();
+ }
+ if ((mResetOptions & RESET_WIFI_MANAGER) != 0) {
+ builder.resetWifiManager();
+ }
+ if ((mResetOptions & RESET_WIFI_P2P_MANAGER) != 0) {
+ builder.resetWifiP2pManager(looper);
+ }
+ if (mResetEsimPackageName != null) {
+ builder.resetEsim(mResetEsimPackageName);
+ }
+ if (mResetTelephonyManager != INVALID_SUBSCRIPTION_ID) {
+ builder.resetTelephonyAndNetworkPolicyManager(mResetTelephonyManager);
+ }
+ if ((mResetOptions & RESET_BLUETOOTH_MANAGER) != 0) {
+ builder.resetBluetoothManager();
+ }
+ if (mResetApn != INVALID_SUBSCRIPTION_ID) {
+ builder.resetApn(mResetApn);
+ }
+ return builder;
+ }
+}
diff --git a/src/com/android/settings/TrustedCredentialsFragment.java b/src/com/android/settings/TrustedCredentialsFragment.java
index ca565a4..c90a44d 100644
--- a/src/com/android/settings/TrustedCredentialsFragment.java
+++ b/src/com/android/settings/TrustedCredentialsFragment.java
@@ -25,7 +25,6 @@
import android.app.Activity;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
-import android.app.settings.SettingsEnums;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -68,7 +67,7 @@
import com.android.internal.app.UnlaunchableAppActivity;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.TrustedCredentialsSettings.Tab;
-import com.android.settings.core.InstrumentedFragment;
+import com.android.settingslib.core.lifecycle.ObservableFragment;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
@@ -81,7 +80,7 @@
/**
* Fragment to display trusted credentials settings for one tab.
*/
-public class TrustedCredentialsFragment extends InstrumentedFragment
+public class TrustedCredentialsFragment extends ObservableFragment
implements TrustedCredentialsDialogBuilder.DelegateInterface {
public static final String ARG_POSITION = "tab";
@@ -176,11 +175,6 @@
return mFragmentView;
}
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.TRUSTED_CREDENTIALS;
- }
-
private void createChildView(
LayoutInflater inflater, ViewGroup parent, Bundle childState, int i) {
boolean isWork = mGroupAdapter.getUserInfoByGroup(i).isManagedProfile();
diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
index 0bd9996..ab3716e 100644
--- a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
+++ b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java
@@ -208,7 +208,7 @@
final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule(
activityFilters,
intent,
- true /* stickyPlaceholder */,
+ false /* stickyPlaceholder */,
SplitRule.FINISH_ADJACENT,
ActivityEmbeddingUtils.getMinCurrentScreenSplitWidthPx(mContext),
ActivityEmbeddingUtils.getMinSmallestScreenSplitWidthPx(mContext),
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 155583e..3261d6c 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -258,7 +258,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.DIALOG_APP_INFO_ACTION;
+ return SettingsEnums.DIALOG_BASE_APP_INFO_ACTION;
}
@Override
diff --git a/src/com/android/settings/applications/appinfo/InstantAppButtonDialogFragment.java b/src/com/android/settings/applications/appinfo/InstantAppButtonDialogFragment.java
index 6376d52..5a6d3df 100644
--- a/src/com/android/settings/applications/appinfo/InstantAppButtonDialogFragment.java
+++ b/src/com/android/settings/applications/appinfo/InstantAppButtonDialogFragment.java
@@ -49,7 +49,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.DIALOG_APP_INFO_ACTION;
+ return SettingsEnums.DIALOG_INSTANT_APP_INFO_ACTION;
}
@Override
diff --git a/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java b/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java
index 4251346..d17f843 100644
--- a/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java
+++ b/src/com/android/settings/applications/appinfo/WriteSettingsDetails.java
@@ -113,7 +113,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.SYSTEM_ALERT_WINDOW_APPS;
+ return SettingsEnums.MODIFY_SYSTEM_SETTINGS;
}
public static CharSequence getSummary(Context context, AppEntry entry) {
diff --git a/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java b/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java
index c8f4c0b..6c59745 100644
--- a/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java
+++ b/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java
@@ -19,6 +19,7 @@
import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_NONE;
import android.app.Dialog;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.verify.domain.DomainOwner;
@@ -113,7 +114,7 @@
@Override
public int getMetricsCategory() {
- return 0;
+ return SettingsEnums.PROGRESS_DIALOG;
}
/**
diff --git a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java
index dd5b746..e67fa04 100644
--- a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java
+++ b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java
@@ -17,6 +17,7 @@
package com.android.settings.applications.intentpicker;
import android.app.Dialog;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.verify.domain.DomainVerificationManager;
@@ -73,7 +74,7 @@
@Override
public int getMetricsCategory() {
- return 0;
+ return SettingsEnums.SUPPORTED_LINKS_DIALOG;
}
/** Display the dialog. */
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index fa5852e..4701d0d 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -527,7 +527,7 @@
case LIST_TYPE_OVERLAY:
return SettingsEnums.SYSTEM_ALERT_WINDOW_APPS;
case LIST_TYPE_WRITE_SETTINGS:
- return SettingsEnums.SYSTEM_ALERT_WINDOW_APPS;
+ return SettingsEnums.MODIFY_SYSTEM_SETTINGS;
case LIST_TYPE_MANAGE_SOURCES:
return SettingsEnums.MANAGE_EXTERNAL_SOURCES;
case LIST_TYPE_WIFI_ACCESS:
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 2f1fcf3..08fb5c0 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -331,7 +331,7 @@
@Override
public void onClick(LinkSpan span) {
- if ("url".equals(span.getId())) {
+ if ("url".equals(span.getLink())) {
String url = getString(R.string.help_url_fingerprint);
Intent intent = HelpUtils.getHelpIntent(this, url, getClass().getName());
if (intent == null) {
diff --git a/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java b/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java
deleted file mode 100644
index 9a0cab2..0000000
--- a/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java
+++ /dev/null
@@ -1,57 +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.biometrics2.factory;
-
-import android.app.Application;
-import android.app.admin.DevicePolicyManager;
-
-import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentFactory;
-import androidx.lifecycle.ViewModelProvider;
-
-import com.android.settings.biometrics2.ui.view.FingerprintEnrollIntroFragment;
-
-/**
- * Fragment factory for biometrics
- */
-public class BiometricsFragmentFactory extends FragmentFactory {
-
- private final Application mApplication;
- private final ViewModelProvider mViewModelProvider;
-
- public BiometricsFragmentFactory(Application application,
- ViewModelProvider viewModelProvider) {
- mApplication = application;
- mViewModelProvider = viewModelProvider;
- }
-
- @NonNull
- @Override
- public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) {
- final Class<? extends Fragment> clazz = loadFragmentClass(classLoader, className);
- if (FingerprintEnrollIntroFragment.class.equals(clazz)) {
- final DevicePolicyManager devicePolicyManager =
- mApplication.getSystemService(DevicePolicyManager.class);
- if (devicePolicyManager != null) {
- return new FingerprintEnrollIntroFragment(mViewModelProvider,
- devicePolicyManager.getResources());
- }
- }
- return super.instantiate(classLoader, className);
- }
-}
diff --git a/src/com/android/settings/biometrics2/ui/model/CredentialModel.java b/src/com/android/settings/biometrics2/ui/model/CredentialModel.java
index 06caf5e..b943608 100644
--- a/src/com/android/settings/biometrics2/ui/model/CredentialModel.java
+++ b/src/com/android/settings/biometrics2/ui/model/CredentialModel.java
@@ -22,6 +22,7 @@
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE;
import android.content.Intent;
+import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -80,18 +81,31 @@
@Nullable
private Long mClearGkPwHandleMillis = null;
- public CredentialModel(@NonNull Intent intent, @NonNull Clock clock) {
- mUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
- mSensorId = intent.getIntExtra(EXTRA_KEY_SENSOR_ID, INVALID_SENSOR_ID);
- mChallenge = intent.getLongExtra(EXTRA_KEY_CHALLENGE, INVALID_CHALLENGE);
- mToken = intent.getByteArrayExtra(EXTRA_KEY_CHALLENGE_TOKEN);
- mGkPwHandle = intent.getLongExtra(EXTRA_KEY_GK_PW_HANDLE,
- INVALID_GK_PW_HANDLE);
+ public CredentialModel(@NonNull Bundle bundle, @NonNull Clock clock) {
+ mUserId = bundle.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId());
+ mSensorId = bundle.getInt(EXTRA_KEY_SENSOR_ID, INVALID_SENSOR_ID);
+ mChallenge = bundle.getLong(EXTRA_KEY_CHALLENGE, INVALID_CHALLENGE);
+ mToken = bundle.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN);
+ mGkPwHandle = bundle.getLong(EXTRA_KEY_GK_PW_HANDLE, INVALID_GK_PW_HANDLE);
mClock = clock;
mInitMillis = mClock.millis();
}
/**
+ * Get a bundle which can be used to recreate CredentialModel
+ */
+ @NonNull
+ public Bundle getBundle() {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(Intent.EXTRA_USER_ID, mUserId);
+ bundle.putInt(EXTRA_KEY_SENSOR_ID, mSensorId);
+ bundle.putLong(EXTRA_KEY_CHALLENGE, mChallenge);
+ bundle.putByteArray(EXTRA_KEY_CHALLENGE_TOKEN, mToken);
+ bundle.putLong(EXTRA_KEY_GK_PW_HANDLE, mGkPwHandle);
+ return bundle;
+ }
+
+ /**
* Get userId for this credential
*/
public int getUserId() {
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java
index 2308f2e..ecec36f 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java
@@ -25,7 +25,7 @@
import static com.google.android.setupdesign.util.DynamicColorPalette.ColorType.ACCENT;
import android.app.Activity;
-import android.app.admin.DevicePolicyResourcesManager;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
@@ -44,6 +44,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
+import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModelProvider;
import com.android.settings.R;
@@ -63,9 +64,6 @@
private static final String TAG = "FingerprintEnrollIntroFragment";
- @NonNull private final ViewModelProvider mViewModelProvider;
- @Nullable private final DevicePolicyResourcesManager mDevicePolicyMgrRes;
-
private FingerprintEnrollIntroViewModel mViewModel = null;
private View mView = null;
@@ -75,12 +73,8 @@
private TextView mFooterMessage6 = null;
@Nullable private PorterDuffColorFilter mIconColorFilter;
- public FingerprintEnrollIntroFragment(
- @NonNull ViewModelProvider viewModelProvider,
- @Nullable DevicePolicyResourcesManager devicePolicyMgrRes) {
+ public FingerprintEnrollIntroFragment() {
super();
- mViewModelProvider = viewModelProvider;
- mDevicePolicyMgrRes = devicePolicyMgrRes;
}
@Nullable
@@ -127,15 +121,6 @@
footerTitle2.setText(
R.string.security_settings_fingerprint_enroll_introduction_footer_title_2);
- return mView;
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- final Context context = view.getContext();
-
final TextView footerLink = mView.findViewById(R.id.footer_learn_more);
footerLink.setMovementMethod(LinkMovementMethod.getInstance());
final String footerLinkStr = getContext().getString(
@@ -146,18 +131,28 @@
// footer buttons
mPrimaryFooterButton = new FooterButton.Builder(context)
.setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
- .setListener(mViewModel::onNextButtonClick)
.setButtonType(FooterButton.ButtonType.OPT_IN)
.setTheme(R.style.SudGlifButton_Primary)
.build();
mSecondaryFooterButton = new FooterButton.Builder(context)
- .setListener(mViewModel::onSkipOrCancelButtonClick)
.setButtonType(FooterButton.ButtonType.NEXT)
.setTheme(R.style.SudGlifButton_Primary)
.build();
getFooterBarMixin().setPrimaryButton(mPrimaryFooterButton);
getFooterBarMixin().setSecondaryButton(mSecondaryFooterButton, true /* usePrimaryStyle */);
+ return mView;
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ final Context context = view.getContext();
+
+ mPrimaryFooterButton.setOnClickListener(mViewModel::onNextButtonClick);
+ mSecondaryFooterButton.setOnClickListener(mViewModel::onSkipOrCancelButtonClick);
+
if (mViewModel.canAssumeUdfps()) {
mFooterMessage6.setVisibility(View.VISIBLE);
mIconShield.setVisibility(View.VISIBLE);
@@ -165,7 +160,7 @@
mFooterMessage6.setVisibility(View.GONE);
mIconShield.setVisibility(View.GONE);
}
- mSecondaryFooterButton.setText(getContext(),
+ mSecondaryFooterButton.setText(context,
mViewModel.getEnrollmentRequest().isAfterSuwOrSuwSuggestedAction()
? R.string.security_settings_fingerprint_enroll_introduction_cancel
: R.string.security_settings_fingerprint_enroll_introduction_no_thanks);
@@ -181,23 +176,37 @@
setHeaderText(getActivity(),
R.string.security_settings_fingerprint_enroll_introduction_title);
}
+ observePageStatusLiveDataIfNeed();
+ }
- mViewModel.getPageStatusLiveData().observe(this, this::updateFooterButtons);
+ private void observePageStatusLiveDataIfNeed() {
+ final LiveData<FingerprintEnrollIntroStatus> statusLiveData =
+ mViewModel.getPageStatusLiveData();
+ final FingerprintEnrollIntroStatus status = statusLiveData.getValue();
+ if (status != null && status.hasScrollToBottom()) {
+ // Do not requireScrollWithButton() again when "I agree" or "Done" button is visible,
+ // because if we requireScrollWithButton() again, it will become "More" after scroll-up.
+ return;
+ }
final RequireScrollMixin requireScrollMixin = getLayout()
.getMixin(RequireScrollMixin.class);
requireScrollMixin.requireScrollWithButton(getActivity(), mPrimaryFooterButton,
getMoreButtonTextRes(), mViewModel::onNextButtonClick);
- requireScrollMixin.setOnRequireScrollStateChangedListener(scrollNeeded -> {
- if (!scrollNeeded) {
- mViewModel.setHasScrolledToBottom();
- }
- });
+
+ // Always set true to setHasScrolledToBottom() before registering listener through
+ // setOnRequireScrollStateChangedListener(), because listener will not be called if first
+ // scrollNeeded is true
+ mViewModel.setHasScrolledToBottom(true);
+ requireScrollMixin.setOnRequireScrollStateChangedListener(
+ scrollNeeded -> mViewModel.setHasScrolledToBottom(!scrollNeeded));
+ statusLiveData.observe(this, this::updateFooterButtons);
}
@Override
public void onAttach(@NonNull Context context) {
- mViewModel = mViewModelProvider.get(FingerprintEnrollIntroViewModel.class);
+ mViewModel = new ViewModelProvider(getActivity())
+ .get(FingerprintEnrollIntroViewModel.class);
getLifecycle().addObserver(mViewModel);
super.onAttach(context);
}
@@ -232,12 +241,16 @@
private String getDescriptionDisabledByAdmin(@NonNull Context context) {
final int defaultStrId =
R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled;
- if (mDevicePolicyMgrRes == null) {
+
+ final DevicePolicyManager devicePolicyManager = getActivity()
+ .getSystemService(DevicePolicyManager.class);
+ if (devicePolicyManager != null) {
+ return devicePolicyManager.getResources().getString(FINGERPRINT_UNLOCK_DISABLED,
+ () -> context.getString(defaultStrId));
+ } else {
Log.w(TAG, "getDescriptionDisabledByAdmin, null device policy manager res");
return "";
}
- return mDevicePolicyMgrRes.getString(FINGERPRINT_UNLOCK_DISABLED,
- () -> context.getString(defaultStrId));
}
private void setHeaderText(@NonNull Activity activity, int resId) {
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java
index e9cf6fd..1f67100 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java
@@ -19,20 +19,19 @@
import static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY;
import static com.android.settings.biometrics2.factory.BiometricsViewModelFactory.CHALLENGE_GENERATOR;
-import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK;
+import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_IS_GENERATING_CHALLENGE;
+import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_VALID;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_CONTINUE_ENROLL;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_SKIP_OR_CANCEL;
-import android.app.Activity;
import android.app.Application;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.Bundle;
-import android.os.SystemClock;
import android.util.Log;
import androidx.activity.result.ActivityResult;
@@ -42,7 +41,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
-import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.viewmodel.CreationExtras;
import androidx.lifecycle.viewmodel.MutableCreationExtras;
@@ -51,11 +49,9 @@
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor;
-import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollEnrolling;
+import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFindSensor;
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
-import com.android.settings.biometrics2.factory.BiometricsFragmentFactory;
import com.android.settings.biometrics2.factory.BiometricsViewModelFactory;
-import com.android.settings.biometrics2.ui.model.CredentialModel;
import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel;
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.FingerprintChallengeGenerator;
@@ -99,15 +95,10 @@
mViewModel = viewModelProvider.get(FingerprintEnrollmentViewModel.class);
mViewModel.setRequest(new EnrollmentRequest(getIntent(), getApplicationContext()));
mViewModel.setSavedInstanceState(savedInstanceState);
- getLifecycle().addObserver(mViewModel);
mAutoCredentialViewModel = viewModelProvider.get(AutoCredentialViewModel.class);
- mAutoCredentialViewModel.setCredentialModel(new CredentialModel(getIntent(),
- SystemClock.elapsedRealtimeClock()));
- getLifecycle().addObserver(mAutoCredentialViewModel);
-
- mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult);
- mAutoCredentialViewModel.getActionLiveData().observe(this, this::onCredentialAction);
+ mAutoCredentialViewModel.setCredentialModel(savedInstanceState, getIntent());
+ checkCredential();
// Theme
setTheme(mViewModel.getRequest().getTheme());
@@ -116,21 +107,35 @@
// fragment
setContentView(R.layout.biometric_enrollment_container);
- final FragmentManager fragmentManager = getSupportFragmentManager();
- fragmentManager.setFragmentFactory(
- new BiometricsFragmentFactory(getApplication(), viewModelProvider));
- final FingerprintEnrollIntroViewModel fingerprintEnrollIntroViewModel =
+ final FingerprintEnrollIntroViewModel introViewModel =
viewModelProvider.get(FingerprintEnrollIntroViewModel.class);
- fingerprintEnrollIntroViewModel.setEnrollmentRequest(mViewModel.getRequest());
- fingerprintEnrollIntroViewModel.setUserId(mAutoCredentialViewModel.getUserId());
- fingerprintEnrollIntroViewModel.getActionLiveData().observe(
- this, this::observeIntroAction);
- final String tag = "FingerprintEnrollIntroFragment";
- fragmentManager.beginTransaction()
- .setReorderingAllowed(true)
- .add(R.id.fragment_container_view, FingerprintEnrollIntroFragment.class, null, tag)
- .commit();
+ introViewModel.setEnrollmentRequest(mViewModel.getRequest());
+ introViewModel.setUserId(mAutoCredentialViewModel.getUserId());
+ if (savedInstanceState == null) {
+ final String tag = "FingerprintEnrollIntroFragment";
+ getSupportFragmentManager().beginTransaction()
+ .setReorderingAllowed(true)
+ .add(R.id.fragment_container_view, FingerprintEnrollIntroFragment.class, null,
+ tag)
+ .commit();
+ }
+
+ // observe LiveData
+ getLifecycle().addObserver(mViewModel);
+ mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult);
+
+ mAutoCredentialViewModel.getGenerateChallengeFailedLiveData().observe(this,
+ this::onGenerateChallengeFailed);
+
+ // Clear ActionLiveData in FragmentViewModel to prevent getting previous action during
+ // recreate, like press 'I agree' then press 'back' in FingerprintEnrollFindSensor activity.
+ introViewModel.clearActionLiveData();
+ introViewModel.getActionLiveData().observe(this, this::observeIntroAction);
+ }
+
+ private void onGenerateChallengeFailed(@NonNull Boolean ignoredBoolean) {
+ onSetActivityResult(new ActivityResult(RESULT_CANCELED, null));
}
private void onSetActivityResult(@NonNull ActivityResult result) {
@@ -141,10 +146,10 @@
finish();
}
- private void onCredentialAction(@NonNull Integer action) {
- switch (action) {
+ private void checkCredential() {
+ switch (mAutoCredentialViewModel.checkCredential()) {
case CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK: {
- final Intent intent = mAutoCredentialViewModel.getChooseLockIntent(this,
+ final Intent intent = mAutoCredentialViewModel.createChooseLockIntent(this,
mViewModel.getRequest().isSuw(), mViewModel.getRequest().getSuwExtras());
if (!mViewModel.isWaitingActivityResult().compareAndSet(false, true)) {
Log.w(TAG, "chooseLock, fail to set isWaiting flag to true");
@@ -153,7 +158,7 @@
return;
}
case CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK: {
- final boolean launched = mAutoCredentialViewModel.getConfirmLockLauncher(
+ final boolean launched = mAutoCredentialViewModel.createConfirmLockLauncher(
this,
LAUNCH_CONFIRM_LOCK_ACTIVITY,
getString(R.string.security_settings_fingerprint_preference_title)
@@ -168,12 +173,9 @@
}
return;
}
- case CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE: {
- Log.w(TAG, "observeCredentialLiveData, finish with action:" + action);
- if (mViewModel.getRequest().isAfterSuwOrSuwSuggestedAction()) {
- setResult(Activity.RESULT_CANCELED);
- }
- finish();
+ case CREDENTIAL_VALID:
+ case CREDENTIAL_IS_GENERATING_CHALLENGE: {
+ // Do nothing
}
}
}
@@ -186,10 +188,15 @@
if (mAutoCredentialViewModel.checkNewCredentialFromActivityResult(
isChooseLock, activityResult)) {
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
+ } else {
+ onSetActivityResult(activityResult);
}
}
- private void observeIntroAction(@NonNull Integer action) {
+ private void observeIntroAction(@Nullable Integer action) {
+ if (action == null) {
+ return;
+ }
switch (action) {
case FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH: {
onSetActivityResult(
@@ -207,9 +214,9 @@
Log.w(TAG, "startNext, isSuw:" + isSuw + ", fail to set isWaiting flag");
}
final Intent intent = new Intent(this, isSuw
- ? SetupFingerprintEnrollEnrolling.class
+ ? SetupFingerprintEnrollFindSensor.class
: FingerprintEnrollFindSensor.class);
- intent.putExtras(mAutoCredentialViewModel.getCredentialBundle());
+ intent.putExtras(mAutoCredentialViewModel.createCredentialIntentExtra());
intent.putExtras(mViewModel.getNextActivityBaseIntentExtras());
mNextActivityLauncher.launch(intent);
}
@@ -272,5 +279,6 @@
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
mViewModel.onSaveInstanceState(outState);
+ mAutoCredentialViewModel.onSaveInstanceState(outState);
}
}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java
index b1a7f90..3b7a436 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java
@@ -30,20 +30,21 @@
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.os.SystemClock;
import android.util.Log;
import androidx.activity.result.ActivityResult;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.AndroidViewModel;
-import androidx.lifecycle.DefaultLifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.settings.biometrics.BiometricUtils;
+import com.android.settings.biometrics.BiometricUtils.GatekeeperCredentialNotMatchException;
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
import com.android.settings.biometrics2.ui.model.CredentialModel;
import com.android.settings.password.ChooseLockGeneric;
@@ -57,31 +58,40 @@
* AutoCredentialViewModel which uses CredentialModel to determine next actions for activity, like
* start ChooseLockActivity, start ConfirmLockActivity, GenerateCredential, or do nothing.
*/
-public class AutoCredentialViewModel extends AndroidViewModel implements DefaultLifecycleObserver {
+public class AutoCredentialViewModel extends AndroidViewModel {
private static final String TAG = "AutoCredentialViewModel";
- private static final boolean DEBUG = true;
+
+ @VisibleForTesting
+ static final String KEY_CREDENTIAL_MODEL = "credential_model";
+
+ private static final boolean DEBUG = false;
+
+ /**
+ * Valid credential, activity does nothing.
+ */
+ public static final int CREDENTIAL_VALID = 0;
+
+ /**
+ * This credential looks good, but still need to run generateChallenge().
+ */
+ public static final int CREDENTIAL_IS_GENERATING_CHALLENGE = 1;
/**
* Need activity to run choose lock
*/
- public static final int CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK = 1;
+ public static final int CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK = 2;
/**
* Need activity to run confirm lock
*/
- public static final int CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK = 2;
-
- /**
- * Fail to use challenge from hardware generateChallenge(), shall finish activity with proper
- * error code
- */
- public static final int CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE = 3;
+ public static final int CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK = 3;
@IntDef(prefix = { "CREDENTIAL_" }, value = {
+ CREDENTIAL_VALID,
+ CREDENTIAL_IS_GENERATING_CHALLENGE,
CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK,
- CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK,
- CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE
+ CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK
})
@Retention(RetentionPolicy.SOURCE)
public @interface CredentialAction {}
@@ -157,11 +167,10 @@
}
}
-
@NonNull private final LockPatternUtils mLockPatternUtils;
@NonNull private final ChallengeGenerator mChallengeGenerator;
private CredentialModel mCredentialModel = null;
- @NonNull private final MutableLiveData<Integer> mActionLiveData =
+ @NonNull private final MutableLiveData<Boolean> mGenerateChallengeFailedLiveData =
new MutableLiveData<>();
public AutoCredentialViewModel(
@@ -173,51 +182,65 @@
mChallengeGenerator = challengeGenerator;
}
- public void setCredentialModel(@NonNull CredentialModel credentialModel) {
- mCredentialModel = credentialModel;
+ /**
+ * Set CredentialModel, the source is coming from savedInstanceState or activity intent
+ */
+ public void setCredentialModel(@Nullable Bundle savedInstanceState, @NonNull Intent intent) {
+ final Bundle bundle;
+ if (savedInstanceState != null) {
+ bundle = savedInstanceState.getBundle(KEY_CREDENTIAL_MODEL);
+ } else {
+ bundle = intent.getExtras();
+ }
+ mCredentialModel = new CredentialModel(bundle, SystemClock.elapsedRealtimeClock());
+
+ if (DEBUG) {
+ Log.d(TAG, "setCredentialModel " + mCredentialModel + ", savedInstanceState exist:"
+ + (savedInstanceState != null));
+ }
}
/**
- * Observe ActionLiveData for actions about choosing lock, confirming lock, or finishing
- * activity
+ * Handle onSaveInstanceState from activity
*/
- @NonNull
- public LiveData<Integer> getActionLiveData() {
- return mActionLiveData;
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ outState.putBundle(KEY_CREDENTIAL_MODEL, mCredentialModel.getBundle());
}
- @Override
- public void onCreate(@NonNull LifecycleOwner owner) {
- checkCredential();
+ @NonNull
+ public LiveData<Boolean> getGenerateChallengeFailedLiveData() {
+ return mGenerateChallengeFailedLiveData;
}
/**
* Check credential status for biometric enrollment.
*/
- private void checkCredential() {
+ @CredentialAction
+ public int checkCredential() {
if (isValidCredential()) {
- return;
+ return CREDENTIAL_VALID;
}
final long gkPwHandle = mCredentialModel.getGkPwHandle();
if (isUnspecifiedPassword()) {
- mActionLiveData.postValue(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK);
+ return CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK;
} else if (CredentialModel.isValidGkPwHandle(gkPwHandle)) {
generateChallenge(gkPwHandle);
+ return CREDENTIAL_IS_GENERATING_CHALLENGE;
} else {
- mActionLiveData.postValue(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
+ return CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK;
}
}
private void generateChallenge(long gkPwHandle) {
mChallengeGenerator.setCallback((sensorId, userId, challenge) -> {
- mCredentialModel.setSensorId(sensorId);
- mCredentialModel.setChallenge(challenge);
try {
final byte[] newToken = requestGatekeeperHat(gkPwHandle, challenge, userId);
+ mCredentialModel.setSensorId(sensorId);
+ mCredentialModel.setChallenge(challenge);
mCredentialModel.setToken(newToken);
} catch (IllegalStateException e) {
Log.e(TAG, "generateChallenge, IllegalStateException", e);
- mActionLiveData.postValue(CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE);
+ mGenerateChallengeFailedLiveData.postValue(true);
return;
}
@@ -231,7 +254,7 @@
// Check credential again
if (!isValidCredential()) {
Log.w(TAG, "generateChallenge, invalid Credential");
- mActionLiveData.postValue(CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE);
+ mGenerateChallengeFailedLiveData.postValue(true);
}
});
mChallengeGenerator.generateChallenge(getUserId());
@@ -282,16 +305,16 @@
final VerifyCredentialResponse response = mLockPatternUtils
.verifyGatekeeperPasswordHandle(gkPwHandle, challenge, userId);
if (!response.isMatched()) {
- throw new IllegalStateException("Unable to request Gatekeeper HAT");
+ throw new GatekeeperCredentialNotMatchException("Unable to request Gatekeeper HAT");
}
return response.getGatekeeperHAT();
}
/**
- * Get Credential bundle which will be used to launch next activity.
+ * Get Credential intent extra which will be used to launch next activity.
*/
@NonNull
- public Bundle getCredentialBundle() {
+ public Bundle createCredentialIntentExtra() {
final Bundle retBundle = new Bundle();
final long gkPwHandle = mCredentialModel.getGkPwHandle();
if (CredentialModel.isValidGkPwHandle(gkPwHandle)) {
@@ -311,10 +334,10 @@
}
/**
- * Get Intent for choosing lock
+ * Create Intent for choosing lock
*/
@NonNull
- public Intent getChooseLockIntent(@NonNull Context context, boolean isSuw,
+ public Intent createChooseLockIntent(@NonNull Context context, boolean isSuw,
@NonNull Bundle suwExtras) {
final Intent intent = BiometricUtils.getChooseLockIntent(context, isSuw,
suwExtras);
@@ -331,10 +354,10 @@
}
/**
- * Get ConfirmLockLauncher
+ * Create ConfirmLockLauncher
*/
@NonNull
- public ChooseLockSettingsHelper getConfirmLockLauncher(@NonNull Activity activity,
+ public ChooseLockSettingsHelper createConfirmLockLauncher(@NonNull Activity activity,
int requestCode, @NonNull String title) {
final ChooseLockSettingsHelper.Builder builder =
new ChooseLockSettingsHelper.Builder(activity);
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java
index 252a508..72611a7 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java
@@ -145,6 +145,13 @@
}
/**
+ * Clear user's action live data
+ */
+ public void clearActionLiveData() {
+ mActionLiveData.setValue(null);
+ }
+
+ /**
* Get user's action live data (like clicking Agree, Skip, or Done)
*/
public LiveData<Integer> getActionLiveData() {
@@ -161,8 +168,8 @@
/**
* Update onboarding intro page has scrolled to bottom
*/
- public void setHasScrolledToBottom() {
- mHasScrolledToBottomLiveData.postValue(true);
+ public void setHasScrolledToBottom(boolean value) {
+ mHasScrolledToBottomLiveData.postValue(value);
}
/**
diff --git a/src/com/android/settings/development/RebootWithMteDialog.java b/src/com/android/settings/development/RebootWithMteDialog.java
index b6522a9..858cd8f 100644
--- a/src/com/android/settings/development/RebootWithMteDialog.java
+++ b/src/com/android/settings/development/RebootWithMteDialog.java
@@ -52,7 +52,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.REBOOT_WITH_MTE;
+ return SettingsEnums.REBOOT_WITH_MTE_DIALOG;
}
@Override
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
index bd0772c..759c7d8 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
@@ -48,7 +48,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.DEVICEINFO_STORAGE;
+ return SettingsEnums.PRIVATE_VOLUME_FORGET;
}
@Override
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java b/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java
index dadff3c..3820eb6 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java
@@ -44,7 +44,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.DEVICEINFO_STORAGE;
+ return SettingsEnums.PRIVATE_VOLUME_FORMAT;
}
@Override
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
index 738c3ca..dccb12d 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
@@ -40,7 +40,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.DEVICEINFO_STORAGE;
+ return SettingsEnums.PRIVATE_VOLUME_UNMOUNT;
}
@Override
diff --git a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
index d43b254..4fd63af 100644
--- a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
@@ -95,7 +95,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.DEVICEINFO_STORAGE;
+ return SettingsEnums.PUBLIC_VOLUME_SETTINGS;
}
@Override
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 7a33a62..2faacb7 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -20,10 +20,8 @@
import android.content.Intent;
import android.util.SparseIntArray;
-import com.android.settings.fuelgauge.batteryusage.BatteryHistEntry;
import com.android.settingslib.fuelgauge.Estimate;
-import java.util.Map;
import java.util.Set;
/**
@@ -104,12 +102,6 @@
String getOldEstimateDebugString(String timeRemaining);
/**
- * Returns the string to show in the advanced usage battery page when enhanced estimates are
- * enabled. This string notifies users that the estimate is using enhanced prediction.
- */
- String getAdvancedUsageScreenInfoString();
-
- /**
* Returns a signal to indicate if the device will need to warn the user they may not make it
* to their next charging time.
*
@@ -144,11 +136,6 @@
Intent getResumeChargeIntent();
/**
- * Returns battery history data with corresponding timestamp key.
- */
- Map<Long, Map<String, BatteryHistEntry>> getBatteryHistory(Context context);
-
- /**
* Returns {@link Set} for hidding applications background usage time.
*/
Set<CharSequence> getHideBackgroundUsageTimeSet(Context context);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 3fe4275..ff1edec 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -24,10 +24,8 @@
import android.util.SparseIntArray;
import com.android.internal.util.ArrayUtils;
-import com.android.settings.fuelgauge.batteryusage.BatteryHistEntry;
import com.android.settingslib.fuelgauge.Estimate;
-import java.util.Map;
import java.util.Set;
/** Implementation of {@code PowerUsageFeatureProvider} */
@@ -123,11 +121,6 @@
}
@Override
- public String getAdvancedUsageScreenInfoString() {
- return null;
- }
-
- @Override
public boolean getEarlyWarningSignal(Context context, String id) {
return false;
}
@@ -159,11 +152,6 @@
}
@Override
- public Map<Long, Map<String, BatteryHistEntry>> getBatteryHistory(Context context) {
- return null;
- }
-
- @Override
public Set<CharSequence> getHideBackgroundUsageTimeSet(Context context) {
return new ArraySet<>();
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
index 7382299..0eca3a6 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
@@ -167,7 +167,7 @@
@Override
public int getMetricsCategory() {
- return 0;
+ return SettingsEnums.FUELGAUGE_BATTERY_SAVER_SCHEDULE;
}
private void logPowerSaver() {
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
index d4c00a4..5fd3905 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragment.java
@@ -43,7 +43,6 @@
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
-import java.text.NumberFormat;
import java.util.List;
/**
@@ -142,29 +141,6 @@
.setPositiveButton(R.string.battery_tip_unrestrict_app_dialog_ok, this)
.setNegativeButton(R.string.battery_tip_unrestrict_app_dialog_cancel, null)
.create();
- case BatteryTip.TipType.BATTERY_DEFENDER:
- mMetricsFeatureProvider.action(context,
- SettingsEnums.ACTION_TIP_BATTERY_DEFENDER, mMetricsKey);
- final double chargeLimitLevel = 0.8f;
- final String percentage =
- NumberFormat.getPercentInstance().format(chargeLimitLevel);
- final String message = context.getString(
- R.string.battery_tip_limited_temporarily_dialog_msg, percentage);
- final boolean isPluggedIn = isPluggedIn();
- final AlertDialog.Builder dialogBuilder =
- new AlertDialog.Builder(context)
- .setTitle(R.string.battery_tip_limited_temporarily_title)
- .setMessage(message);
- if (isPluggedIn) {
- dialogBuilder
- .setPositiveButton(
- R.string.battery_tip_limited_temporarily_dialog_resume_charge,
- this)
- .setNegativeButton(R.string.okay, null);
- } else {
- dialogBuilder.setPositiveButton(R.string.okay, null);
- }
- return dialogBuilder.create();
default:
throw new IllegalArgumentException("unknown type " + mBatteryTip.getType());
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java b/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java
deleted file mode 100644
index 824b6be..0000000
--- a/src/com/android/settings/fuelgauge/batterytip/actions/BatteryDefenderAction.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2020 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.actions;
-
-import android.content.Intent;
-
-import com.android.settings.SettingsActivity;
-import com.android.settings.overlay.FeatureFactory;
-
-/**
- * Action to open the Support Center article
- */
-public class BatteryDefenderAction extends BatteryTipAction {
- private SettingsActivity mSettingsActivity;
-
- public BatteryDefenderAction(SettingsActivity settingsActivity) {
- super(settingsActivity.getApplicationContext());
- mSettingsActivity = settingsActivity;
- }
-
- @Override
- public void handlePositiveAction(int metricsKey) {
- final Intent intent = FeatureFactory.getFactory(mContext)
- .getPowerUsageFeatureProvider(mContext).getResumeChargeIntent();
- if (intent != null) {
- mContext.sendBroadcast(intent);
- }
- }
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
index af67610..cb870f4 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
@@ -70,9 +70,6 @@
}
}
- public static final int MSG_UPDATE_NAME_ICON = 1;
- public static final int MSG_REPORT_FULLY_DRAWN = 2;
-
private static final String TAG = "BatteryEntry";
private static final String PACKAGE_SYSTEM = "android";
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
index e376d85..2dba3c2 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
@@ -52,7 +52,6 @@
private static final String KEY_REFRESH_TYPE = "refresh_type";
private static final String KEY_BATTERY_GRAPH = "battery_graph";
private static final String KEY_APP_LIST = "app_list";
- private static final int LOADER_BATTERY_USAGE_STATS = 2;
@VisibleForTesting
BatteryHistoryPreference mHistPref;
@@ -165,7 +164,7 @@
bundle.putInt(KEY_REFRESH_TYPE, refreshType);
if (!mIsChartDataLoaded) {
mIsChartDataLoaded = true;
- getLoaderManager().restartLoader(LOADER_BATTERY_USAGE_STATS, bundle,
+ restartLoader(LoaderIndex.BATTERY_HISTORY_LOADER, bundle,
mBatteryHistoryLoaderCallbacks);
}
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBase.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBase.java
index ccefdf2..ed3a921 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBase.java
@@ -24,6 +24,7 @@
import android.os.UserManager;
import android.util.Log;
+import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
@@ -33,17 +34,19 @@
import com.android.settings.fuelgauge.BatteryBroadcastReceiver;
import com.android.settings.fuelgauge.BatteryUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Common base class for things that need to show the battery usage graph.
*/
public abstract class PowerUsageBase extends DashboardFragment {
-
private static final String TAG = "PowerUsageBase";
- private static final String KEY_REFRESH_TYPE = "refresh_type";
- private static final String KEY_INCLUDE_HISTORY = "include_history";
- private static final int LOADER_BATTERY_USAGE_STATS = 1;
-
+ @VisibleForTesting
+ static final String KEY_REFRESH_TYPE = "refresh_type";
+ @VisibleForTesting
+ static final String KEY_INCLUDE_HISTORY = "include_history";
@VisibleForTesting
BatteryUsageStats mBatteryUsageStats;
@@ -55,6 +58,21 @@
final BatteryUsageStatsLoaderCallbacks mBatteryUsageStatsLoaderCallbacks =
new BatteryUsageStatsLoaderCallbacks();
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ LoaderIndex.BATTERY_USAGE_STATS_LOADER,
+ LoaderIndex.BATTERY_INFO_LOADER,
+ LoaderIndex.BATTERY_TIP_LOADER,
+ LoaderIndex.BATTERY_HISTORY_LOADER
+
+ })
+ public @interface LoaderIndex {
+ int BATTERY_USAGE_STATS_LOADER = 0;
+ int BATTERY_INFO_LOADER = 1;
+ int BATTERY_TIP_LOADER = 2;
+ int BATTERY_HISTORY_LOADER = 3;
+ }
+
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
@@ -91,10 +109,28 @@
final Bundle bundle = new Bundle();
bundle.putInt(KEY_REFRESH_TYPE, refreshType);
bundle.putBoolean(KEY_INCLUDE_HISTORY, isBatteryHistoryNeeded());
- getLoaderManager().restartLoader(LOADER_BATTERY_USAGE_STATS, bundle,
+ restartLoader(LoaderIndex.BATTERY_USAGE_STATS_LOADER, bundle,
mBatteryUsageStatsLoaderCallbacks);
}
+ protected LoaderManager getLoaderManagerForCurrentFragment() {
+ return LoaderManager.getInstance(this);
+ }
+
+ protected void restartLoader(int loaderId, Bundle bundle,
+ LoaderManager.LoaderCallbacks<?> loaderCallbacks) {
+ LoaderManager loaderManager = getLoaderManagerForCurrentFragment();
+ Loader<?> loader = loaderManager.getLoader(
+ loaderId);
+ if (loader != null && !loader.isReset()) {
+ loaderManager.restartLoader(loaderId, bundle,
+ loaderCallbacks);
+ } else {
+ loaderManager.initLoader(loaderId, bundle,
+ loaderCallbacks);
+ }
+ }
+
protected void onLoadFinished(@BatteryUpdateType int refreshType) {
refreshUi(refreshType);
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
index bca32a7..f266492 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
@@ -65,11 +65,6 @@
static final String KEY_BATTERY_USAGE = "battery_usage_summary";
@VisibleForTesting
- static final int BATTERY_INFO_LOADER = 1;
- @VisibleForTesting
- static final int BATTERY_TIP_LOADER = 2;
-
- @VisibleForTesting
PowerUsageFeatureProvider mPowerFeatureProvider;
@VisibleForTesting
BatteryUtils mBatteryUtils;
@@ -241,7 +236,7 @@
@VisibleForTesting
void restartBatteryTipLoader() {
- getLoaderManager().restartLoader(BATTERY_TIP_LOADER, Bundle.EMPTY, mBatteryTipsCallbacks);
+ restartLoader(LoaderIndex.BATTERY_TIP_LOADER, Bundle.EMPTY, mBatteryTipsCallbacks);
}
@VisibleForTesting
@@ -274,8 +269,7 @@
if (!mIsBatteryPresent) {
return;
}
- getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
- mBatteryInfoLoaderCallbacks);
+ restartLoader(LoaderIndex.BATTERY_INFO_LOADER, Bundle.EMPTY, mBatteryInfoLoaderCallbacks);
}
@VisibleForTesting
diff --git a/src/com/android/settings/network/InternetResetHelper.java b/src/com/android/settings/network/InternetResetHelper.java
index 086ef1b..7920cca 100644
--- a/src/com/android/settings/network/InternetResetHelper.java
+++ b/src/com/android/settings/network/InternetResetHelper.java
@@ -21,14 +21,9 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
-import android.os.HandlerThread;
-import android.os.Process;
-import android.text.TextUtils;
import android.util.Log;
-import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
-import androidx.annotation.WorkerThread;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
@@ -38,14 +33,14 @@
import com.android.settingslib.connectivity.ConnectivitySubsystemsRecoveryManager;
import com.android.settingslib.utils.HandlerInjector;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
/**
* Helper class to restart connectivity for all requested subsystems.
*/
-public class InternetResetHelper implements LifecycleObserver,
- ConnectivitySubsystemsRecoveryManager.RecoveryStatusCallback {
+public class InternetResetHelper implements LifecycleObserver {
protected static final String TAG = "InternetResetHelper";
public static final long RESTART_TIMEOUT_MS = 15_000; // 15 seconds
@@ -61,41 +56,40 @@
protected final IntentFilter mWifiStateFilter;
protected final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
@Override
- @WorkerThread
public void onReceive(Context context, Intent intent) {
- if (intent != null && TextUtils.equals(intent.getAction(),
- WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- updateWifiStateChange();
- }
+ updateWifiStateChange();
}
};
- protected ConnectivitySubsystemsRecoveryManager mConnectivitySubsystemsRecoveryManager;
- protected HandlerThread mWorkerThread;
- protected boolean mIsRecoveryReady;
- protected boolean mIsWifiReady;
+ protected RecoveryWorker mRecoveryWorker;
+ protected boolean mIsWifiReady = true;
protected HandlerInjector mHandlerInjector;
- protected final Runnable mResumeRunnable = () -> {
- resumePreferences();
- };
protected final Runnable mTimeoutRunnable = () -> {
- mIsRecoveryReady = true;
+ Log.w(TAG, "Resume preferences due to connectivity subsystems recovery timed out.");
+ mRecoveryWorker.clearRecovering();
mIsWifiReady = true;
resumePreferences();
};
- public InternetResetHelper(Context context, Lifecycle lifecycle) {
+ public InternetResetHelper(Context context, Lifecycle lifecycle,
+ NetworkMobileProviderController mobileNetworkController,
+ Preference wifiTogglePreferences,
+ PreferenceCategory connectedWifiEntryPreferenceCategory,
+ PreferenceCategory firstWifiEntryPreferenceCategory,
+ PreferenceCategory wifiEntryPreferenceCategory,
+ Preference resettingPreference) {
mContext = context;
+ mMobileNetworkController = mobileNetworkController;
+ mWifiTogglePreferences = wifiTogglePreferences;
+ mWifiNetworkPreferences.add(connectedWifiEntryPreferenceCategory);
+ mWifiNetworkPreferences.add(firstWifiEntryPreferenceCategory);
+ mWifiNetworkPreferences.add(wifiEntryPreferenceCategory);
+ mResettingPreference = resettingPreference;
+
mHandlerInjector = new HandlerInjector(context.getMainThreadHandler());
mWifiManager = mContext.getSystemService(WifiManager.class);
mWifiStateFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION);
-
- mWorkerThread = new HandlerThread(TAG
- + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
- Process.THREAD_PRIORITY_BACKGROUND);
- mWorkerThread.start();
- mConnectivitySubsystemsRecoveryManager = new ConnectivitySubsystemsRecoveryManager(
- mContext, mWorkerThread.getThreadHandler());
+ mRecoveryWorker = RecoveryWorker.getInstance(mContext, this);
if (lifecycle != null) {
lifecycle.addObserver(this);
@@ -118,72 +112,18 @@
/** @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) */
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
- mHandlerInjector.removeCallbacks(mResumeRunnable);
mHandlerInjector.removeCallbacks(mTimeoutRunnable);
- mWorkerThread.quit();
- }
-
- @Override
- @WorkerThread
- public void onSubsystemRestartOperationBegin() {
- Log.d(TAG, "The connectivity subsystem is starting for recovery.");
- }
-
- @Override
- @WorkerThread
- public void onSubsystemRestartOperationEnd() {
- Log.d(TAG, "The connectivity subsystem is done for recovery.");
- if (!mIsRecoveryReady) {
- mIsRecoveryReady = true;
- mHandlerInjector.postDelayed(mResumeRunnable, 0 /* delayMillis */);
- }
}
@VisibleForTesting
- @WorkerThread
protected void updateWifiStateChange() {
if (!mIsWifiReady && mWifiManager.isWifiEnabled()) {
Log.d(TAG, "The Wi-Fi subsystem is done for recovery.");
mIsWifiReady = true;
- mHandlerInjector.postDelayed(mResumeRunnable, 0 /* delayMillis */);
+ resumePreferences();
}
}
- /**
- * Sets the resetting preference.
- */
- @UiThread
- public void setResettingPreference(Preference preference) {
- mResettingPreference = preference;
- }
-
- /**
- * Sets the mobile network controller.
- */
- @UiThread
- public void setMobileNetworkController(NetworkMobileProviderController controller) {
- mMobileNetworkController = controller;
- }
-
- /**
- * Sets the Wi-Fi toggle preference.
- */
- @UiThread
- public void setWifiTogglePreference(Preference preference) {
- mWifiTogglePreferences = preference;
- }
-
- /**
- * Adds the Wi-Fi network preference.
- */
- @UiThread
- public void addWifiNetworkPreference(PreferenceCategory preference) {
- if (preference != null) {
- mWifiNetworkPreferences.add(preference);
- }
- }
-
- @UiThread
protected void suspendPreferences() {
Log.d(TAG, "Suspend the subsystem preferences");
if (mMobileNetworkController != null) {
@@ -201,9 +141,9 @@
}
}
- @UiThread
protected void resumePreferences() {
- if (mIsRecoveryReady && mMobileNetworkController != null) {
+ boolean isRecoveryReady = !mRecoveryWorker.isRecovering();
+ if (isRecoveryReady && mMobileNetworkController != null) {
Log.d(TAG, "Resume the Mobile Network controller");
mMobileNetworkController.hidePreference(false /* hide */, true /* immediately */);
}
@@ -214,7 +154,7 @@
pref.setVisible(true);
}
}
- if (mIsRecoveryReady && mIsWifiReady) {
+ if (isRecoveryReady && mIsWifiReady) {
mHandlerInjector.removeCallbacks(mTimeoutRunnable);
if (mResettingPreference != null) {
Log.d(TAG, "Resume the Resetting preference");
@@ -223,21 +163,99 @@
}
}
- /**
- * Restart connectivity for all requested subsystems.
- */
- @UiThread
+ protected void showResettingAndSendTimeoutChecks() {
+ suspendPreferences();
+ mHandlerInjector.postDelayed(mTimeoutRunnable, RESTART_TIMEOUT_MS);
+ }
+
+ /** Restart connectivity for all requested subsystems. */
public void restart() {
- if (!mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()) {
+ if (!mRecoveryWorker.isRecoveryAvailable()) {
Log.e(TAG, "The connectivity subsystem is not available to restart.");
return;
}
-
- Log.d(TAG, "The connectivity subsystem is restarting for recovery.");
- suspendPreferences();
- mIsRecoveryReady = false;
+ showResettingAndSendTimeoutChecks();
mIsWifiReady = !mWifiManager.isWifiEnabled();
- mHandlerInjector.postDelayed(mTimeoutRunnable, RESTART_TIMEOUT_MS);
- mConnectivitySubsystemsRecoveryManager.triggerSubsystemRestart(null /* reason */, this);
+ mRecoveryWorker.triggerRestart();
+ }
+
+ /** Check if the connectivity subsystem is under recovering. */
+ public void checkRecovering() {
+ if (!mRecoveryWorker.isRecovering()) return;
+ mIsWifiReady = false;
+ showResettingAndSendTimeoutChecks();
+ }
+
+ /**
+ * This is a singleton class for ConnectivitySubsystemsRecoveryManager worker.
+ */
+ @VisibleForTesting
+ public static class RecoveryWorker implements
+ ConnectivitySubsystemsRecoveryManager.RecoveryStatusCallback {
+ private static final String TAG = "RecoveryWorker";
+ private static RecoveryWorker sInstance;
+ private static WeakReference<InternetResetHelper> sCallback;
+ private static ConnectivitySubsystemsRecoveryManager sRecoveryManager;
+ private static boolean sIsRecovering;
+
+ /**
+ * Create a singleton class for ConnectivitySubsystemsRecoveryManager.
+ *
+ * @param context The context to use for the content resolver.
+ * @param callback The callback of {@link InternetResetHelper} object.
+ * @return an instance of {@link RecoveryWorker} object.
+ */
+ public static RecoveryWorker getInstance(Context context, InternetResetHelper callback) {
+ sCallback = new WeakReference<>(callback);
+ if (sInstance != null) return sInstance;
+
+ sInstance = new RecoveryWorker();
+ Context appContext = context.getApplicationContext();
+ sRecoveryManager = new ConnectivitySubsystemsRecoveryManager(appContext,
+ appContext.getMainThreadHandler());
+ return sInstance;
+ }
+
+ /** Returns true, If the subsystem service is recovering. */
+ public boolean isRecovering() {
+ return sIsRecovering;
+ }
+
+ /** Clear the recovering flag. */
+ public void clearRecovering() {
+ sIsRecovering = false;
+ }
+
+ /** Returns true, If the subsystem service is recovery available. */
+ public boolean isRecoveryAvailable() {
+ return sRecoveryManager.isRecoveryAvailable();
+ }
+
+ /** Trigger connectivity recovery for all requested technologies. */
+ public boolean triggerRestart() {
+ if (!isRecoveryAvailable()) {
+ Log.e(TAG, "The connectivity subsystem is not available to restart.");
+ return false;
+ }
+ sIsRecovering = true;
+ sRecoveryManager.triggerSubsystemRestart(null /* reason */, sInstance);
+ Log.d(TAG, "The connectivity subsystem is restarting for recovery.");
+ return true;
+ }
+
+ @Override
+ public void onSubsystemRestartOperationBegin() {
+ Log.d(TAG, "The connectivity subsystem is starting for recovery.");
+ sIsRecovering = true;
+ }
+
+ @Override
+ public void onSubsystemRestartOperationEnd() {
+ Log.d(TAG, "The connectivity subsystem is done for recovery.");
+ sIsRecovering = false;
+ InternetResetHelper callback = sCallback.get();
+ if (callback == null) return;
+ callback.resumePreferences();
+ }
}
}
diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java
index f688138..5de4c72 100644
--- a/src/com/android/settings/network/MobileNetworkRepository.java
+++ b/src/com/android/settings/network/MobileNetworkRepository.java
@@ -88,6 +88,7 @@
private Uri mAirplaneModeSettingUri;
private MetricsFeatureProvider mMetricsFeatureProvider;
private IntentFilter mFilter = new IntentFilter();
+ private MobileDataContentObserver mDataContentObserver;
private int mPhysicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
private int mLogicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
@@ -125,6 +126,13 @@
mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao();
mAirplaneModeObserver = new AirplaneModeObserver(new Handler(Looper.getMainLooper()));
mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
+ mDataContentObserver = new MobileDataContentObserver(
+ new Handler(Looper.getMainLooper()));
+ mDataContentObserver.setOnMobileDataChangedListener(() -> {
+ mExecutor.execute(() -> {
+ insertMobileNetworkInfo(context);
+ });
+ });
mFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED);
mFilter.addAction(ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
@@ -163,6 +171,9 @@
public void addRegister(LifecycleOwner lifecycleOwner) {
mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this);
mAirplaneModeObserver.register(mContext);
+ if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ mDataContentObserver.register(mContext, mSubId);
+ }
mContext.registerReceiver(mDataSubscriptionChangedReceiver, mFilter);
observeAllSubInfo(lifecycleOwner);
observeAllUiccInfo(lifecycleOwner);
@@ -170,6 +181,9 @@
}
public void removeRegister() {
+ if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ mDataContentObserver.unRegister(mContext);
+ }
mAirplaneModeObserver.unRegister(mContext);
if (mDataSubscriptionChangedReceiver != null) {
mContext.unregisterReceiver(mDataSubscriptionChangedReceiver);
@@ -404,7 +418,7 @@
return new MobileNetworkInfoEntity(String.valueOf(mSubId),
MobileNetworkUtils.isContactDiscoveryEnabled(context, mSubId),
MobileNetworkUtils.isContactDiscoveryVisible(context, mSubId),
- MobileNetworkUtils.isMobileDataEnabled(context),
+ mTelephonyManager.isDataEnabled(),
MobileNetworkUtils.isCdmaOptions(context, mSubId),
MobileNetworkUtils.isGsmOptions(context, mSubId),
MobileNetworkUtils.isWorldMode(context, mSubId),
diff --git a/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java b/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java
index abde7c0..421a854 100644
--- a/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java
+++ b/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java
@@ -41,6 +41,7 @@
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.mobile.dataservice.DataServiceUtils;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
import com.android.settingslib.mobile.dataservice.UiccInfoEntity;
@@ -181,10 +182,7 @@
@Override
public void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
- if ((mSubInfoEntityList != null &&
- (subInfoEntityList.isEmpty() || !subInfoEntityList.equals(mSubInfoEntityList)))
- || (!subInfoEntityList.isEmpty() && mSubInfoEntityList == null)) {
- Log.d(TAG, "subInfo list from framework is changed, update the subInfo entity list.");
+ if (DataServiceUtils.shouldUpdateEntityList(mSubInfoEntityList, subInfoEntityList)) {
mSubInfoEntityList = subInfoEntityList;
mPreferenceCategory.setVisible(isAvailable());
update();
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index b622a3c..7b7cdca 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -337,6 +337,8 @@
addConnectedEthernetNetworkController();
addWifiSwitchPreferenceController();
mWifiStatusMessagePreference = findPreference(PREF_KEY_WIFI_STATUS_MESSAGE);
+
+ checkConnectivityRecovering();
}
private void updateAirplaneModeMsgPreference(boolean visible) {
@@ -382,6 +384,17 @@
mWifiSwitchPreferenceController.displayPreference(getPreferenceScreen());
}
+ private void checkConnectivityRecovering() {
+ mInternetResetHelper = new InternetResetHelper(getContext(), getLifecycle(),
+ mNetworkMobileProviderController,
+ findPreference(WifiSwitchPreferenceController.KEY),
+ mConnectedWifiEntryPreferenceCategory,
+ mFirstWifiEntryPreferenceCategory,
+ mWifiEntryPreferenceCategory,
+ mResetInternetPreference);
+ mInternetResetHelper.checkRecovering();
+ }
+
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -1455,16 +1468,6 @@
EventLog.writeEvent(0x534e4554, "252995826", UserHandle.myUserId(), "User is a guest");
return;
}
- if (mInternetResetHelper == null) {
- mInternetResetHelper = new InternetResetHelper(getContext(), getLifecycle());
- mInternetResetHelper.setResettingPreference(mResetInternetPreference);
- mInternetResetHelper.setMobileNetworkController(mNetworkMobileProviderController);
- mInternetResetHelper.setWifiTogglePreference(
- findPreference(WifiSwitchPreferenceController.KEY));
- mInternetResetHelper.addWifiNetworkPreference(mConnectedWifiEntryPreferenceCategory);
- mInternetResetHelper.addWifiNetworkPreference(mFirstWifiEntryPreferenceCategory);
- mInternetResetHelper.addWifiNetworkPreference(mWifiEntryPreferenceCategory);
- }
mInternetResetHelper.restart();
}
diff --git a/src/com/android/settings/network/ResetNetworkOperationBuilder.java b/src/com/android/settings/network/ResetNetworkOperationBuilder.java
index 3b5c9bc..3583d06 100644
--- a/src/com/android/settings/network/ResetNetworkOperationBuilder.java
+++ b/src/com/android/settings/network/ResetNetworkOperationBuilder.java
@@ -28,8 +28,10 @@
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Looper;
import android.os.RecoverySystem;
+import android.os.SystemClock;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.util.Log;
import com.android.settings.network.apn.ApnSettings;
@@ -43,6 +45,10 @@
*/
public class ResetNetworkOperationBuilder {
+ private static final String TAG = "ResetNetworkOpBuilder";
+
+ private static final boolean DRY_RUN = false;
+
private Context mContext;
private List<Runnable> mResetSequence = new ArrayList<Runnable>();
@@ -127,10 +133,17 @@
public ResetNetworkOperationBuilder resetEsim(String callerPackage,
Consumer<Boolean> resultCallback) {
Runnable runnable = () -> {
- Boolean wipped = RecoverySystem.wipeEuiccData(mContext, callerPackage);
- if (resultCallback != null) {
- resultCallback.accept(wipped);
+ long startTime = SystemClock.elapsedRealtime();
+
+ if (!DRY_RUN) {
+ Boolean wipped = RecoverySystem.wipeEuiccData(mContext, callerPackage);
+ if (resultCallback != null) {
+ resultCallback.accept(wipped);
+ }
}
+
+ long endTime = SystemClock.elapsedRealtime();
+ Log.i(TAG, "Reset eSIM, takes " + (endTime - startTime) + " ms");
};
mResetSequence.add(runnable);
return this;
@@ -179,14 +192,21 @@
*/
public ResetNetworkOperationBuilder resetApn(int subscriptionId) {
Runnable runnable = () -> {
+ long startTime = SystemClock.elapsedRealtime();
+
Uri uri = Uri.parse(ApnSettings.RESTORE_CARRIERS_URI);
if (SubscriptionManager.isUsableSubscriptionId(subscriptionId)) {
uri = Uri.withAppendedPath(uri, "subId/" + String.valueOf(subscriptionId));
}
- ContentResolver resolver = mContext.getContentResolver();
- resolver.delete(uri, null, null);
+ if (!DRY_RUN) {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.delete(uri, null, null);
+ }
+
+ long endTime = SystemClock.elapsedRealtime();
+ Log.i(TAG, "Reset " + uri + ", takes " + (endTime - startTime) + " ms");
};
mResetSequence.add(runnable);
return this;
@@ -205,7 +225,14 @@
if (service == null) {
return;
}
- Runnable runnable = () -> serviceAccess.accept(service);
+ Runnable runnable = () -> {
+ long startTime = SystemClock.elapsedRealtime();
+ if (!DRY_RUN) {
+ serviceAccess.accept(service);
+ }
+ long endTime = SystemClock.elapsedRealtime();
+ Log.i(TAG, "Reset " + serviceName + ", takes " + (endTime - startTime) + " ms");
+ };
mResetSequence.add(runnable);
}
}
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index 69951bf..8543770 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -16,14 +16,19 @@
package com.android.settings.network.telephony;
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
-import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.OnLifecycleEvent;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
@@ -32,16 +37,22 @@
import com.android.settings.R;
import com.android.settings.network.MobileDataContentObserver;
+import com.android.settings.network.MobileNetworkRepository;
import com.android.settings.wifi.WifiPickerTrackerHelper;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.mobile.dataservice.DataServiceUtils;
+import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
+import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
+import com.android.settingslib.mobile.dataservice.UiccInfoEntity;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Preference controller for "Mobile data"
*/
public class MobileDataPreferenceController extends TelephonyTogglePreferenceController
- implements LifecycleObserver, OnStart, OnStop {
+ implements LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback {
private static final String DIALOG_TAG = "MobileDataDialog";
@@ -56,12 +67,26 @@
boolean mNeedDialog;
private WifiPickerTrackerHelper mWifiPickerTrackerHelper;
+ protected MobileNetworkRepository mMobileNetworkRepository;
+ protected LifecycleOwner mLifecycleOwner;
+ private List<SubscriptionInfoEntity> mSubscriptionInfoEntityList = new ArrayList<>();
+ private List<MobileNetworkInfoEntity> mMobileNetworkInfoEntityList = new ArrayList<>();
+ private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ SubscriptionInfoEntity mSubscriptionInfoEntity;
+ MobileNetworkInfoEntity mMobileNetworkInfoEntity;
- public MobileDataPreferenceController(Context context, String key) {
+ public MobileDataPreferenceController(Context context, String key, Lifecycle lifecycle,
+ LifecycleOwner lifecycleOwner, int subId) {
super(context, key);
+ mSubId = subId;
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mDataContentObserver = new MobileDataContentObserver(new Handler(Looper.getMainLooper()));
mDataContentObserver.setOnMobileDataChangedListener(() -> updateState(mPreference));
+ mMobileNetworkRepository = MobileNetworkRepository.createBySubId(context, this, mSubId);
+ mLifecycleOwner = lifecycleOwner;
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
}
@Override
@@ -77,18 +102,14 @@
mPreference = screen.findPreference(getPreferenceKey());
}
- @Override
+ @OnLifecycleEvent(ON_START)
public void onStart() {
- if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- mDataContentObserver.register(mContext, mSubId);
- }
+ mMobileNetworkRepository.addRegister(mLifecycleOwner);
}
- @Override
+ @OnLifecycleEvent(ON_STOP)
public void onStop() {
- if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- mDataContentObserver.unRegister(mContext);
- }
+ mMobileNetworkRepository.removeRegister();
}
@Override
@@ -122,39 +143,47 @@
@Override
public boolean isChecked() {
- mTelephonyManager = getTelephonyManager();
- return mTelephonyManager.isDataEnabled();
+ return mMobileNetworkInfoEntity == null ? false
+ : mMobileNetworkInfoEntity.isMobileDataEnabled;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- if (isOpportunistic()) {
- preference.setEnabled(false);
- preference.setSummary(R.string.mobile_data_settings_summary_auto_switch);
- } else {
- preference.setEnabled(true);
- preference.setSummary(R.string.mobile_data_settings_summary);
+ mPreference = (SwitchPreference) preference;
+ update();
+ }
+
+ private void update() {
+
+ if (mSubscriptionInfoEntity == null || mPreference == null) {
+ return;
}
- if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- preference.setSelectable(false);
- preference.setSummary(R.string.mobile_data_settings_summary_unavailable);
+ mPreference.setChecked(isChecked());
+ if (mSubscriptionInfoEntity.isOpportunistic) {
+ mPreference.setEnabled(false);
+ mPreference.setSummary(R.string.mobile_data_settings_summary_auto_switch);
} else {
- preference.setSelectable(true);
+ mPreference.setEnabled(true);
+ mPreference.setSummary(R.string.mobile_data_settings_summary);
+ }
+ if (!mSubscriptionInfoEntity.isValidSubscription) {
+ mPreference.setSelectable(false);
+ mPreference.setSummary(R.string.mobile_data_settings_summary_unavailable);
+ } else {
+ mPreference.setSelectable(true);
}
}
- private boolean isOpportunistic() {
- SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
- return info != null && info.isOpportunistic();
- }
-
- public void init(FragmentManager fragmentManager, int subId) {
+ public void init(FragmentManager fragmentManager, int subId,
+ SubscriptionInfoEntity subInfoEntity, MobileNetworkInfoEntity networkInfoEntity) {
mFragmentManager = fragmentManager;
mSubId = subId;
mTelephonyManager = null;
mTelephonyManager = getTelephonyManager();
+ mSubscriptionInfoEntity = subInfoEntity;
+ mMobileNetworkInfoEntity = networkInfoEntity;
}
private TelephonyManager getTelephonyManager() {
@@ -179,9 +208,8 @@
final boolean enableData = !isChecked();
mTelephonyManager = getTelephonyManager();
final boolean isMultiSim = (mTelephonyManager.getActiveModemCount() > 1);
- final int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId();
- final boolean needToDisableOthers = mSubscriptionManager
- .isActiveSubscriptionId(defaultSubId) && defaultSubId != mSubId;
+ final boolean needToDisableOthers = mDefaultSubId != mSubId;
+
if (enableData && isMultiSim && needToDisableOthers) {
mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG;
return true;
@@ -194,4 +222,62 @@
mSubId);
dialogFragment.show(mFragmentManager, DIALOG_TAG);
}
+
+ @VisibleForTesting
+ public void setSubscriptionInfoEntity(SubscriptionInfoEntity subscriptionInfoEntity) {
+ mSubscriptionInfoEntity = subscriptionInfoEntity;
+ }
+
+ @VisibleForTesting
+ public void setMobileNetworkInfoEntity(MobileNetworkInfoEntity mobileNetworkInfoEntity) {
+ mMobileNetworkInfoEntity = mobileNetworkInfoEntity;
+ }
+
+ @Override
+ public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
+ }
+
+ @Override
+ public void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
+ }
+
+ @Override
+ public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList) {
+ if (DataServiceUtils.shouldUpdateEntityList(mSubscriptionInfoEntityList,
+ subInfoEntityList)) {
+ mSubscriptionInfoEntityList = subInfoEntityList;
+ mSubscriptionInfoEntityList.forEach(entity -> {
+ if (Integer.parseInt(entity.subId) == mSubId) {
+ mSubscriptionInfoEntity = entity;
+ }
+ });
+ if (mSubscriptionInfoEntity != null
+ && mSubscriptionInfoEntity.isDefaultDataSubscription) {
+ mDefaultSubId = Integer.parseInt(mSubscriptionInfoEntity.subId);
+ }
+ update();
+ refreshSummary(mPreference);
+ }
+ }
+
+ @Override
+ public void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) {
+ }
+
+ @Override
+ public void onAllMobileNetworkInfoChanged(
+ List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
+ if (DataServiceUtils.shouldUpdateEntityList(mMobileNetworkInfoEntityList,
+ mobileNetworkInfoEntityList)) {
+ mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList;
+ mMobileNetworkInfoEntityList.forEach(entity -> {
+ if (Integer.parseInt(entity.subId) == mSubId) {
+ mMobileNetworkInfoEntity = entity;
+ update();
+ refreshSummary(mPreference);
+ return;
+ }
+ });
+ }
+ }
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index df7fd83..88c3656 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -79,6 +79,7 @@
private static final String KEY_ROAMING_PREF = "button_roaming_key";
private static final String KEY_CALLS_PREF = "calls_preference";
private static final String KEY_SMS_PREF = "sms_preference";
+ private static final String KEY_MOBILE_DATA_PREF = "mobile_data_enable";
//String keys for preference lookup
private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
@@ -175,7 +176,9 @@
new CallsDefaultSubscriptionController(context, KEY_CALLS_PREF,
getSettingsLifecycle(), this),
new SmsDefaultSubscriptionController(context, KEY_SMS_PREF, getSettingsLifecycle(),
- this));
+ this),
+ new MobileDataPreferenceController(context, KEY_MOBILE_DATA_PREF,
+ getSettingsLifecycle(), this, mSubId));
}
@Override
@@ -231,10 +234,16 @@
REQUEST_CODE_DELETE_SUBSCRIPTION);
use(DisableSimFooterPreferenceController.class).init(mSubId);
use(NrDisabledInDsdsFooterPreferenceController.class).init(mSubId);
- use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId);
- use(MobileDataPreferenceController.class).setWifiPickerTrackerHelper(
- new WifiPickerTrackerHelper(getSettingsLifecycle(), context,
- null /* WifiPickerTrackerCallback */));
+
+ final MobileDataPreferenceController mobileDataPreferenceController =
+ use(MobileDataPreferenceController.class);
+ if (mobileDataPreferenceController != null) {
+ mobileDataPreferenceController.init(getFragmentManager(), mSubId,
+ mSubscriptionInfoEntity, mMobileNetworkInfoEntity);
+ mobileDataPreferenceController.setWifiPickerTrackerHelper(
+ new WifiPickerTrackerHelper(getSettingsLifecycle(), context,
+ null /* WifiPickerTrackerCallback */));
+ }
final RoamingPreferenceController roamingPreferenceController =
use(RoamingPreferenceController.class);
diff --git a/src/com/android/settings/notification/RedactionInterstitial.java b/src/com/android/settings/notification/RedactionInterstitial.java
index f243250..d6fdaf8 100644
--- a/src/com/android/settings/notification/RedactionInterstitial.java
+++ b/src/com/android/settings/notification/RedactionInterstitial.java
@@ -189,13 +189,16 @@
}
private void loadFromSettings() {
+ final boolean showUnRedactedDefault = getContext().getResources().getBoolean(
+ R.bool.default_allow_sensitive_lockscreen_content);
final boolean managedProfile = UserManager.get(getContext()).isManagedProfile(mUserId);
// Hiding all notifications is device-wide setting, managed profiles can only set
// whether their notifications are show in full or redacted.
final boolean showNotifications = managedProfile || Settings.Secure.getIntForUser(
getContentResolver(), LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, mUserId) != 0;
final boolean showUnredacted = Settings.Secure.getIntForUser(
- getContentResolver(), LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, mUserId) != 0;
+ getContentResolver(), LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
+ showUnRedactedDefault ? 1 : 0, mUserId) != 0;
int checkedButtonId = R.id.hide_all;
if (showNotifications) {
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index e4d52ba..85c203d 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -28,6 +28,7 @@
import android.os.UserManager;
import android.util.Log;
+import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
@@ -109,19 +110,23 @@
@VisibleForTesting @NonNull LockPatternUtils mLockPatternUtils;
@NonNull private final Activity mActivity;
@Nullable private final Fragment mFragment;
+ @Nullable private final ActivityResultLauncher mActivityResultLauncher;
@NonNull private final Builder mBuilder;
private ChooseLockSettingsHelper(@NonNull Builder builder, @NonNull Activity activity,
- @Nullable Fragment fragment) {
+ @Nullable Fragment fragment,
+ @Nullable ActivityResultLauncher activityResultLauncher) {
mBuilder = builder;
mActivity = activity;
mFragment = fragment;
+ mActivityResultLauncher = activityResultLauncher;
mLockPatternUtils = new LockPatternUtils(activity);
}
public static class Builder {
@NonNull private final Activity mActivity;
@Nullable private Fragment mFragment;
+ @Nullable private ActivityResultLauncher mActivityResultLauncher;
private int mRequestCode;
@Nullable private CharSequence mTitle;
@@ -265,6 +270,18 @@
return this;
}
+ /**
+ * Support of ActivityResultLauncher.
+ *
+ * Which allowing the launch operation be controlled externally.
+ * @param activityResultLauncher a launcher previously prepared.
+ */
+ @NonNull public Builder setActivityResultLauncher(
+ ActivityResultLauncher activityResultLauncher) {
+ mActivityResultLauncher = activityResultLauncher;
+ return this;
+ }
+
@NonNull public ChooseLockSettingsHelper build() {
if (!mAllowAnyUserId && mUserId != LockPatternUtils.USER_FRP) {
Utils.enforceSameOwner(mActivity, mUserId);
@@ -282,7 +299,8 @@
+ " ReturnCredentials. Are you sure this is what you want?");
}
- return new ChooseLockSettingsHelper(this, mActivity, mFragment);
+ return new ChooseLockSettingsHelper(this, mActivity, mFragment,
+ mActivityResultLauncher);
}
public boolean show() {
@@ -369,13 +387,17 @@
if (external) {
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
copyOptionalExtras(inIntent, intent);
- if (mFragment != null) {
+ if (mActivityResultLauncher != null) {
+ mActivityResultLauncher.launch(intent);
+ } else if (mFragment != null) {
mFragment.startActivity(intent);
} else {
mActivity.startActivity(intent);
}
} else {
- if (mFragment != null) {
+ if (mActivityResultLauncher != null) {
+ mActivityResultLauncher.launch(intent);
+ } else if (mFragment != null) {
mFragment.startActivityForResult(intent, request);
} else {
mActivity.startActivityForResult(intent, request);
diff --git a/tests/componenttests/Android.bp b/tests/componenttests/Android.bp
index 77ee164..5c03aa9 100644
--- a/tests/componenttests/Android.bp
+++ b/tests/componenttests/Android.bp
@@ -26,6 +26,7 @@
"androidx.test.runner",
"androidx.test.rules",
"androidx.test.ext.junit",
+ "mockito-target",
],
test_suites: ["device-tests"],
diff --git a/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java b/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java
index 78a2c92..df3dd2e 100644
--- a/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java
+++ b/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java
@@ -20,6 +20,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +33,7 @@
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
+import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -40,6 +43,9 @@
import com.android.settings.Settings;
import com.android.settings.testutils.CommonUtils;
import com.android.settings.testutils.UiUtils;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
+import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
import org.junit.After;
import org.junit.Assume;
@@ -47,6 +53,8 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
import java.io.IOException;
import java.net.URL;
@@ -54,6 +62,12 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MobileDataPreferenceControllerComponentTest {
+
+ @Mock
+ private Lifecycle mLifecycle;
+ @Mock
+ private LifecycleOwner mLifecycleOwner;
+
public static final int TIMEOUT = 2000;
private static int sSubscriptionId = 2;
public final String TAG = this.getClass().getName();
@@ -116,9 +130,11 @@
try {
URL url = new URL("https://www.google.net");
MobileDataPreferenceController controller = new MobileDataPreferenceController(
- mInstrumentation.getTargetContext(), "mobile_data");
+ mInstrumentation.getTargetContext(), "mobile_data", mLifecycle,
+ mLifecycleOwner, sSubscriptionId);
FragmentManager manager = ((FragmentActivity) activity).getSupportFragmentManager();
- controller.init(manager, sSubscriptionId);
+ controller.init(manager, sSubscriptionId, mock(SubscriptionInfoEntity.class), mock(
+ MobileNetworkInfoEntity.class));
// Make sure mobile network can connect at first.
assertThat(UiUtils.waitUntilCondition(1000,
diff --git a/tests/robotests/src/com/android/settings/ResetNetworkConfirmTest.java b/tests/robotests/src/com/android/settings/ResetNetworkConfirmTest.java
index 4f870d3..5dad40d 100644
--- a/tests/robotests/src/com/android/settings/ResetNetworkConfirmTest.java
+++ b/tests/robotests/src/com/android/settings/ResetNetworkConfirmTest.java
@@ -31,6 +31,9 @@
import androidx.fragment.app.FragmentActivity;
+import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settings.testutils.shadow.ShadowRecoverySystem;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@@ -43,8 +46,11 @@
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowRecoverySystem.class, ShadowBluetoothAdapter.class})
public class ResetNetworkConfirmTest {
+ private static final String TEST_PACKAGE = "com.android.settings";
+
private FragmentActivity mActivity;
@Mock
@@ -59,9 +65,28 @@
mResetNetworkConfirm.mActivity = mActivity;
}
+ @After
+ public void tearDown() {
+ ShadowRecoverySystem.reset();
+ }
+
+ @Test
+ public void testResetNetworkData_notResetEsim() {
+ mResetNetworkConfirm.mResetNetworkRequest =
+ new ResetNetworkRequest(ResetNetworkRequest.RESET_NONE);
+
+ mResetNetworkConfirm.mFinalClickListener.onClick(null /* View */);
+ Robolectric.getBackgroundThreadScheduler().advanceToLastPostedRunnable();
+
+ assertThat(ShadowRecoverySystem.getWipeEuiccCalledCount()).isEqualTo(0);
+ }
+
@Test
public void setSubtitle_eraseEsim() {
- mResetNetworkConfirm.mEraseEsim = true;
+ mResetNetworkConfirm.mResetNetworkRequest =
+ new ResetNetworkRequest(ResetNetworkRequest.RESET_NONE);
+ mResetNetworkConfirm.mResetNetworkRequest.setResetEsim(TEST_PACKAGE);
+
mResetNetworkConfirm.mContentView =
LayoutInflater.from(mActivity).inflate(R.layout.reset_network_confirm, null);
@@ -74,7 +99,9 @@
@Test
public void setSubtitle_notEraseEsim() {
- mResetNetworkConfirm.mEraseEsim = false;
+ mResetNetworkConfirm.mResetNetworkRequest =
+ new ResetNetworkRequest(ResetNetworkRequest.RESET_NONE);
+
mResetNetworkConfirm.mContentView =
LayoutInflater.from(mActivity).inflate(R.layout.reset_network_confirm, null);
diff --git a/tests/robotests/src/com/android/settings/ResetNetworkTest.java b/tests/robotests/src/com/android/settings/ResetNetworkTest.java
index d703279..0c2c7e8 100644
--- a/tests/robotests/src/com/android/settings/ResetNetworkTest.java
+++ b/tests/robotests/src/com/android/settings/ResetNetworkTest.java
@@ -28,6 +28,7 @@
import android.widget.CheckBox;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
@@ -48,6 +49,7 @@
}
@Test
+ @Ignore
public void showFinalConfirmation_checkboxVisible_eraseEsimChecked() {
mResetNetwork.mEsimContainer.setVisibility(View.VISIBLE);
mResetNetwork.mEsimCheckbox.setChecked(true);
@@ -55,8 +57,8 @@
mResetNetwork.showFinalConfirmation();
Intent intent = shadowOf(mActivity).getNextStartedActivity();
- assertThat(intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
- .getBoolean(MainClear.ERASE_ESIMS_EXTRA, false)).isTrue();
+ assertThat(intent.getStringExtra(ResetNetworkRequest.KEY_ESIM_PACKAGE))
+ .isNotNull();
}
@Test
@@ -67,8 +69,8 @@
mResetNetwork.showFinalConfirmation();
Intent intent = shadowOf(mActivity).getNextStartedActivity();
- assertThat(intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
- .getBoolean(MainClear.ERASE_ESIMS_EXTRA, false)).isFalse();
+ assertThat(intent.getStringExtra(ResetNetworkRequest.KEY_ESIM_PACKAGE))
+ .isNull();
}
@Test
@@ -79,8 +81,8 @@
mResetNetwork.showFinalConfirmation();
Intent intent = shadowOf(mActivity).getNextStartedActivity();
- assertThat(intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
- .getBoolean(MainClear.ERASE_ESIMS_EXTRA, false)).isFalse();
+ assertThat(intent.getStringExtra(ResetNetworkRequest.KEY_ESIM_PACKAGE))
+ .isNull();
}
@Test
@@ -91,7 +93,7 @@
mResetNetwork.showFinalConfirmation();
Intent intent = shadowOf(mActivity).getNextStartedActivity();
- assertThat(intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
- .getBoolean(MainClear.ERASE_ESIMS_EXTRA, false)).isFalse();
+ assertThat(intent.getStringExtra(ResetNetworkRequest.KEY_ESIM_PACKAGE))
+ .isNull();
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java
index 270a625..dc9cac4 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java
@@ -1,5 +1,6 @@
package com.android.settings.fuelgauge.batterysaver;
+import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -82,6 +83,12 @@
verifySchedule("key_battery_saver_percentage", expectedPercentage);
}
+ @Test
+ public void getMetricsCategory_returnExpectedResult() {
+ assertThat(mBatterySaverScheduleSettings.getMetricsCategory())
+ .isEqualTo(SettingsEnums.FUELGAUGE_BATTERY_SAVER_SCHEDULE);
+ }
+
private void setSchedule(int scheduleType, int schedulePercentage) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.AUTOMATIC_POWER_SAVE_MODE, scheduleType);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
index db1159e..c5d66a6 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipDialogFragmentTest.java
@@ -244,20 +244,4 @@
assertThat(shadowDialog.getMessage()).isEqualTo(
mContext.getText(R.string.battery_tip_dialog_summary_message));
}
-
- @Test
- public void testOnCreateDialog_defenderTip_fireDialog() {
- mDialogFragment = BatteryTipDialogFragment.newInstance(mDefenderTip, METRICS_KEY);
-
- FragmentController.setupFragment(mDialogFragment, FragmentActivity.class,
- 0 /* containerViewId */, null /* bundle */);
-
- final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
- ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
-
- assertThat(shadowDialog.getTitle()).isEqualTo(
- mContext.getString(R.string.battery_tip_limited_temporarily_title));
- assertThat(shadowDialog.getMessage()).isEqualTo(
- mContext.getString(R.string.battery_tip_limited_temporarily_dialog_msg, "80%"));
- }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBaseTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBaseTest.java
index 2700930..6ed10cd 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBaseTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageBaseTest.java
@@ -15,18 +15,26 @@
*/
package com.android.settings.fuelgauge.batteryusage;
+import static com.android.settings.fuelgauge.batteryusage.PowerUsageBase.KEY_INCLUDE_HISTORY;
+import static com.android.settings.fuelgauge.batteryusage.PowerUsageBase.KEY_REFRESH_TYPE;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.refEq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.os.BatteryUsageStats;
import android.os.Bundle;
import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
+import com.android.settings.fuelgauge.BatteryBroadcastReceiver;
import com.android.settings.testutils.shadow.ShadowDashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -46,14 +54,15 @@
@Mock
private LoaderManager mLoaderManager;
+ @Mock
+ private Loader<BatteryUsageStats> mBatteryUsageStatsLoader;
private TestFragment mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mFragment = spy(new TestFragment());
- doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+ mFragment = spy(new TestFragment(mLoaderManager));
}
@Test
@@ -63,7 +72,62 @@
verify(mLoaderManager, never()).initLoader(anyInt(), any(Bundle.class), any());
}
- public static class TestFragment extends PowerUsageBase {
+ @Test
+ public void restartBatteryInfoLoader() {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(KEY_REFRESH_TYPE, BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_STATUS);
+ bundle.putBoolean(KEY_INCLUDE_HISTORY, false);
+ doReturn(mBatteryUsageStatsLoader).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_USAGE_STATS_LOADER);
+ doReturn(false).when(mBatteryUsageStatsLoader).isReset();
+
+ mFragment.restartBatteryStatsLoader(
+ BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_STATUS);
+
+ verify(mLoaderManager)
+ .restartLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_USAGE_STATS_LOADER),
+ refEq(bundle), any());
+ }
+
+ @Test
+ public void restartBatteryInfoLoader_loaderReset_initLoader() {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(KEY_REFRESH_TYPE, BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_STATUS);
+ bundle.putBoolean(KEY_INCLUDE_HISTORY, false);
+ doReturn(mBatteryUsageStatsLoader).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_USAGE_STATS_LOADER);
+ doReturn(true).when(mBatteryUsageStatsLoader).isReset();
+
+ mFragment.restartBatteryStatsLoader(
+ BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_STATUS);
+
+ verify(mLoaderManager)
+ .initLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_USAGE_STATS_LOADER),
+ refEq(bundle), any());
+ }
+
+ @Test
+ public void restartBatteryInfoLoader_nullLoader_initLoader() {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(KEY_REFRESH_TYPE, BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_STATUS);
+ bundle.putBoolean(KEY_INCLUDE_HISTORY, false);
+ doReturn(null).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_USAGE_STATS_LOADER);
+
+ mFragment.restartBatteryStatsLoader(
+ BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_STATUS);
+
+ verify(mLoaderManager).initLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_USAGE_STATS_LOADER),
+ refEq(bundle), any());
+ }
+
+ private static class TestFragment extends PowerUsageBase {
+
+ private LoaderManager mLoaderManager;
+
+ TestFragment(LoaderManager loaderManager) {
+ mLoaderManager = loaderManager;
+ }
@Override
public int getMetricsCategory() {
@@ -94,5 +158,10 @@
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return null;
}
+
+ @Override
+ protected LoaderManager getLoaderManagerForCurrentFragment() {
+ return mLoaderManager;
+ }
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryTest.java
index e134490..e44d92c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummaryTest.java
@@ -15,7 +15,6 @@
*/
package com.android.settings.fuelgauge.batteryusage;
-import static com.android.settings.fuelgauge.batteryusage.PowerUsageSummary.BATTERY_INFO_LOADER;
import static com.android.settings.fuelgauge.batteryusage.PowerUsageSummary.KEY_BATTERY_ERROR;
import static com.android.settings.fuelgauge.batteryusage.PowerUsageSummary.KEY_BATTERY_USAGE;
@@ -39,14 +38,17 @@
import android.provider.Settings;
import androidx.loader.app.LoaderManager;
+import androidx.loader.content.Loader;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.fuelgauge.BatteryBroadcastReceiver;
+import com.android.settings.fuelgauge.BatteryInfo;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
+import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -69,8 +71,6 @@
// TODO: Improve this test class so that it starts up the real activity and fragment.
@RunWith(RobolectricTestRunner.class)
public class PowerUsageSummaryTest {
-
- private static final long TIME_SINCE_LAST_FULL_CHARGE_MS = 120 * 60 * 1000;
private static Intent sAdditionalBatteryInfoIntent;
@BeforeClass
@@ -83,6 +83,10 @@
@Mock
private LoaderManager mLoaderManager;
@Mock
+ private Loader<BatteryTip> mBatteryTipLoader;
+ @Mock
+ private Loader<BatteryInfo> mBatteryInfoLoader;
+ @Mock
private ContentResolver mContentResolver;
@Mock
private BatteryBroadcastReceiver mBatteryBroadcastReceiver;
@@ -105,11 +109,9 @@
mRealContext = spy(RuntimeEnvironment.application);
mFeatureFactory = FakeFeatureFactory.setupForTest();
- mFragment = spy(new TestFragment(mRealContext));
+ mFragment = spy(new TestFragment(mRealContext, mLoaderManager));
mFragment.initFeatureProvider();
doNothing().when(mFragment).restartBatteryStatsLoader(anyInt());
- doReturn(mock(LoaderManager.class)).when(mFragment).getLoaderManager();
-
when(mFragment.getActivity()).thenReturn(mSettingsActivity);
when(mFeatureFactory.powerUsageFeatureProvider.getAdditionalBatteryInfoIntent())
.thenReturn(sAdditionalBatteryInfoIntent);
@@ -153,12 +155,58 @@
@Test
public void restartBatteryTipLoader() {
//TODO: add policy logic here when BatteryTipPolicy is implemented
- doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+ doReturn(mBatteryTipLoader).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_TIP_LOADER);
+ doReturn(false).when(mBatteryTipLoader).isReset();
mFragment.restartBatteryTipLoader();
- verify(mLoaderManager)
- .restartLoader(eq(PowerUsageSummary.BATTERY_TIP_LOADER), eq(Bundle.EMPTY), any());
+ verify(mLoaderManager).restartLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_TIP_LOADER),
+ eq(Bundle.EMPTY), any());
+ }
+
+ @Test
+ public void restartBatteryTipLoader_nullLoader_initLoader() {
+ doReturn(null).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_TIP_LOADER);
+
+ mFragment.restartBatteryTipLoader();
+
+ verify(mLoaderManager).initLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_TIP_LOADER),
+ eq(Bundle.EMPTY), any());
+ }
+
+ @Test
+ public void restartBatteryTipLoader_loaderReset_initLoader() {
+ doReturn(mBatteryTipLoader).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_TIP_LOADER);
+ doReturn(true).when(mBatteryTipLoader).isReset();
+
+ mFragment.restartBatteryTipLoader();
+
+
+ verify(mLoaderManager).initLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_TIP_LOADER),
+ eq(Bundle.EMPTY), any());
+ }
+
+
+ @Test
+ public void refreshUi_contextNull_doNothing() {
+ doReturn(null).when(mFragment).getContext();
+
+ mFragment.refreshUi(BatteryBroadcastReceiver.BatteryUpdateType.MANUAL);
+
+ verify(mFragment, never()).restartBatteryTipLoader();
+ verify(mFragment, never()).restartBatteryInfoLoader();
+ }
+
+ @Test
+ public void refreshUi_batteryNotPresent_doNothing() {
+ mFragment.setIsBatteryPresent(false);
+ mFragment.refreshUi(BatteryBroadcastReceiver.BatteryUpdateType.MANUAL);
+
+ verify(mFragment, never()).restartBatteryTipLoader();
+ verify(mFragment, never()).restartBatteryInfoLoader();
}
@Test
@@ -166,10 +214,12 @@
mFragment.mBatteryTipPreferenceController = mock(BatteryTipPreferenceController.class);
when(mFragment.mBatteryTipPreferenceController.needUpdate()).thenReturn(false);
mFragment.updateBatteryTipFlag(new Bundle());
+ doNothing().when(mFragment).restartBatteryInfoLoader();
mFragment.refreshUi(BatteryBroadcastReceiver.BatteryUpdateType.MANUAL);
verify(mFragment, never()).restartBatteryTipLoader();
+ verify(mFragment).restartBatteryInfoLoader();
}
@Test
@@ -177,10 +227,12 @@
mFragment.mBatteryTipPreferenceController = mock(BatteryTipPreferenceController.class);
when(mFragment.mBatteryTipPreferenceController.needUpdate()).thenReturn(true);
mFragment.updateBatteryTipFlag(new Bundle());
+ doNothing().when(mFragment).restartBatteryInfoLoader();
mFragment.refreshUi(BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_LEVEL);
verify(mFragment, never()).restartBatteryTipLoader();
+ verify(mFragment).restartBatteryInfoLoader();
}
@Test
@@ -188,10 +240,13 @@
mFragment.mBatteryTipPreferenceController = mock(BatteryTipPreferenceController.class);
when(mFragment.mBatteryTipPreferenceController.needUpdate()).thenReturn(true);
mFragment.updateBatteryTipFlag(new Bundle());
+ doNothing().when(mFragment).restartBatteryInfoLoader();
+ doNothing().when(mFragment).restartBatteryTipLoader();
mFragment.refreshUi(BatteryBroadcastReceiver.BatteryUpdateType.MANUAL);
verify(mFragment).restartBatteryTipLoader();
+ verify(mFragment).restartBatteryInfoLoader();
}
@Test
@@ -215,19 +270,68 @@
@Test
public void restartBatteryInfoLoader_contextNull_doNothing() {
when(mFragment.getContext()).thenReturn(null);
- when(mFragment.getLoaderManager()).thenReturn(mLoaderManager);
mFragment.restartBatteryInfoLoader();
- verify(mLoaderManager, never()).restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
+ verify(mLoaderManager, never()).restartLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_INFO_LOADER, Bundle.EMPTY,
mFragment.mBatteryInfoLoaderCallbacks);
}
- public static class TestFragment extends PowerUsageSummary {
- private Context mContext;
+ @Test
+ public void restartBatteryInfoLoader_batteryIsNotPresent_doNothing() {
+ mFragment.setIsBatteryPresent(false);
- public TestFragment(Context context) {
+ mFragment.restartBatteryInfoLoader();
+
+ verify(mLoaderManager, never()).restartLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_INFO_LOADER, Bundle.EMPTY,
+ mFragment.mBatteryInfoLoaderCallbacks);
+ }
+
+ @Test
+ public void restartBatteryInfoLoader() {
+ doReturn(mBatteryInfoLoader).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_INFO_LOADER);
+ doReturn(false).when(mBatteryTipLoader).isReset();
+
+ mFragment.restartBatteryInfoLoader();
+
+ verify(mLoaderManager).restartLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_INFO_LOADER),
+ eq(Bundle.EMPTY), any());
+ }
+
+ @Test
+ public void restartBatteryInfoLoader_nullLoader_initLoader() {
+ doReturn(null).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_INFO_LOADER);
+
+ mFragment.restartBatteryInfoLoader();
+
+ verify(mLoaderManager).initLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_INFO_LOADER),
+ eq(Bundle.EMPTY), any());
+ }
+
+ @Test
+ public void restartBatteryInfoLoader_loaderReset_initLoader() {
+ mFragment.setIsBatteryPresent(true);
+ doReturn(mBatteryInfoLoader).when(mLoaderManager).getLoader(
+ PowerUsageBase.LoaderIndex.BATTERY_INFO_LOADER);
+ doReturn(true).when(mBatteryInfoLoader).isReset();
+
+ mFragment.restartBatteryInfoLoader();
+
+ verify(mLoaderManager).initLoader(eq(PowerUsageBase.LoaderIndex.BATTERY_INFO_LOADER),
+ eq(Bundle.EMPTY), any());
+ }
+
+ private static class TestFragment extends PowerUsageSummary {
+ private Context mContext;
+ private LoaderManager mLoaderManager;
+
+ TestFragment(Context context, LoaderManager loaderManager) {
mContext = context;
+ mLoaderManager = loaderManager;
}
@Override
@@ -240,5 +344,15 @@
// Override it so we can access this method in test
return super.getContentResolver();
}
+
+ public void setIsBatteryPresent(boolean isBatteryPresent) {
+ mIsBatteryPresent = isBatteryPresent;
+ }
+
+ @Override
+ protected LoaderManager getLoaderManagerForCurrentFragment() {
+ return mLoaderManager;
+ }
}
+
}
diff --git a/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java b/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
index 5c6da49..9d475b8 100644
--- a/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RedactionInterstitialTest.java
@@ -21,6 +21,7 @@
import com.android.settings.R;
import com.android.settings.RestrictedRadioButton;
import com.android.settings.notification.RedactionInterstitial.RedactionInterstitialFragment;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -38,6 +39,7 @@
@Config(shadows = {
ShadowUtils.class,
ShadowRestrictedLockUtilsInternal.class,
+ SettingsShadowResources.class,
})
public class RedactionInterstitialTest {
private RedactionInterstitial mActivity;
@@ -134,6 +136,28 @@
assertSelectedButton(R.id.redact_sensitive);
}
+ @Test
+ public void defaultShowSensitiveContent_configDeny() {
+ final ContentResolver resolver = RuntimeEnvironment.application.getContentResolver();
+ Settings.Secure.putIntForUser(resolver,
+ LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, UserHandle.myUserId());
+ setupConfig(false);
+ setupActivity();
+
+ assertSelectedButton(R.id.redact_sensitive);
+ }
+
+ @Test
+ public void defaultShowSensitiveContent_configAllow() {
+ final ContentResolver resolver = RuntimeEnvironment.application.getContentResolver();
+ Settings.Secure.putIntForUser(resolver,
+ LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, UserHandle.myUserId());
+ setupConfig(true);
+ setupActivity();
+
+ assertSelectedButton(R.id.show_all);
+ }
+
private void setupActivity() {
mActivity = buildActivity(RedactionInterstitial.class, new Intent()).setup().get();
mFragment = (RedactionInterstitialFragment)
@@ -142,6 +166,11 @@
assertThat(mFragment).isNotNull();
}
+ private void setupConfig(boolean allowSensitiveContent) {
+ SettingsShadowResources.overrideResource(
+ R.bool.default_allow_sensitive_lockscreen_content, allowSensitiveContent);
+ }
+
private void setupSettings(int show, int showUnredacted) {
final ContentResolver resolver = RuntimeEnvironment.application.getContentResolver();
Settings.Secure.putIntForUser(resolver,
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppAllServicesPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppAllServicesPreferenceTest.kt
index 9846e3f..bd73d8b 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppAllServicesPreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppAllServicesPreferenceTest.kt
@@ -30,6 +30,7 @@
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotDisplayed
+import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
@@ -38,6 +39,8 @@
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
+import com.android.settingslib.spa.testutils.delay
+import com.android.settingslib.spa.testutils.waitUntilExists
import com.android.settingslib.spaprivileged.model.app.userHandle
import com.android.settingslib.spaprivileged.model.app.userId
import com.google.common.truth.Truth.assertThat
@@ -140,7 +143,7 @@
setContent()
- composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
+ composeTestRule.waitUntilExists(hasText(SUMMARY))
}
@Test
@@ -149,6 +152,7 @@
setContent()
composeTestRule.onRoot().performClick()
+ composeTestRule.delay()
val intentCaptor = ArgumentCaptor.forClass(Intent::class.java)
verify(context).startActivityAsUser(intentCaptor.capture(), eq(APP.userHandle))
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppLocalePreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppLocalePreferenceTest.kt
index 60c4f79..39524df 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppLocalePreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppLocalePreferenceTest.kt
@@ -24,6 +24,7 @@
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
+import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
@@ -36,6 +37,8 @@
import com.android.settings.applications.AppLocaleUtil
import com.android.settings.applications.appinfo.AppLocaleDetails
import com.android.settings.localepicker.AppLocalePickerActivity
+import com.android.settingslib.spa.testutils.delay
+import com.android.settingslib.spa.testutils.waitUntilExists
import com.android.settingslib.spaprivileged.model.app.userHandle
import com.google.common.truth.Truth.assertThat
import org.junit.After
@@ -103,15 +106,16 @@
composeTestRule.onNodeWithText(context.getString(R.string.app_locale_preference_title))
.assertIsDisplayed()
- composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
+ composeTestRule.waitUntilExists(hasText(SUMMARY))
}
@Test
- fun whenCanDisplayLocalUi_click_startsActivity() {
+ fun whenCanDisplayLocalUi_click_startActivity() {
doNothing().`when`(context).startActivityAsUser(any(), any())
setContent()
composeTestRule.onRoot().performClick()
+ composeTestRule.delay()
val intentCaptor = ArgumentCaptor.forClass(Intent::class.java)
verify(context).startActivityAsUser(intentCaptor.capture(), eq(APP.userHandle))
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppSettingsPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppSettingsPreferenceTest.kt
index a1fb367..35811e2 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppSettingsPreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppSettingsPreferenceTest.kt
@@ -36,6 +36,7 @@
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
+import com.android.settingslib.spa.testutils.delay
import com.android.settingslib.spaprivileged.model.app.userHandle
import com.android.settingslib.spaprivileged.model.app.userId
import com.google.common.truth.Truth.assertThat
@@ -129,6 +130,7 @@
setContent()
composeTestRule.onRoot().performClick()
+ composeTestRule.delay()
val intentCaptor = ArgumentCaptor.forClass(Intent::class.java)
verify(context).startActivityAsUser(intentCaptor.capture(), eq(APP.userHandle))
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
index aeccb07..f4489c6 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
@@ -24,6 +24,7 @@
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotDisplayed
+import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
@@ -34,6 +35,8 @@
import com.android.settings.R
import com.android.settings.applications.appinfo.AppInfoDashboardFragment
import com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesDetails
+import com.android.settingslib.spa.testutils.delay
+import com.android.settingslib.spa.testutils.waitUntilExists
import com.android.settingslib.spaprivileged.framework.common.crossProfileApps
import org.junit.After
import org.junit.Before
@@ -110,7 +113,7 @@
setContent()
- composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
+ composeTestRule.waitUntilExists(hasText(SUMMARY))
}
@Test
@@ -119,6 +122,7 @@
setContent()
composeTestRule.onRoot().performClick()
+ composeTestRule.delay()
ExtendedMockito.verify {
AppInfoDashboardFragment.startAppInfoFragment(
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java
new file mode 100644
index 0000000..1fac8b5
--- /dev/null
+++ b/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.biometrics2.ui.model;
+
+import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE;
+import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_SENSOR_ID;
+import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_CHALLENGE;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.annotation.NonNull;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+import androidx.annotation.Nullable;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.password.ChooseLockSettingsHelper;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Clock;
+import java.util.Arrays;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+public class CredentialModelTest {
+
+ private final Clock mClock = SystemClock.elapsedRealtimeClock();
+
+ public static Bundle newCredentialModelIntentExtras(int userId, long challenge, int sensorId,
+ @Nullable byte[] token, long gkPwHandle) {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(Intent.EXTRA_USER_ID, userId);
+ bundle.putInt(EXTRA_KEY_SENSOR_ID, sensorId);
+ bundle.putLong(EXTRA_KEY_CHALLENGE, challenge);
+ bundle.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+ bundle.putLong(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
+ return bundle;
+ }
+
+ public static Bundle newValidTokenCredentialIntentExtras(int userId) {
+ return newCredentialModelIntentExtras(userId, 1L, 1, new byte[] { 0 }, 0L);
+ }
+
+ public static Bundle newInvalidChallengeCredentialIntentExtras(int userId) {
+ return newCredentialModelIntentExtras(userId, INVALID_CHALLENGE, 1, null, 0L);
+ }
+
+ public static Bundle newGkPwHandleCredentialIntentExtras(int userId, long gkPwHandle) {
+ return newCredentialModelIntentExtras(userId, INVALID_CHALLENGE, 1, null, gkPwHandle);
+ }
+
+ private static void checkBundleLongValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2,
+ @NonNull String key) {
+ if (!bundle1.containsKey(key)) {
+ return;
+ }
+ final int value1 = bundle1.getInt(key);
+ final int value2 = bundle2.getInt(key);
+ assertWithMessage("bundle not match, key:" + key + ", value1:" + value1 + ", value2:"
+ + value2).that(value1).isEqualTo(value2);
+ }
+
+ private static void checkBundleIntValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2,
+ @NonNull String key) {
+ if (!bundle1.containsKey(key)) {
+ return;
+ }
+ final long value1 = bundle1.getLong(key);
+ final long value2 = bundle2.getLong(key);
+ assertWithMessage("bundle not match, key:" + key + ", value1:" + value1 + ", value2:"
+ + value2).that(value1).isEqualTo(value2);
+ }
+
+ private static void checkBundleByteArrayValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2,
+ @NonNull String key) {
+ if (!bundle1.containsKey(key)) {
+ return;
+ }
+ final byte[] value1 = bundle1.getByteArray(key);
+ final byte[] value2 = bundle2.getByteArray(key);
+ final String errMsg = "bundle not match, key:" + key + ", value1:" + Arrays.toString(value1)
+ + ", value2:" + Arrays.toString(value2);
+ if (value1 == null) {
+ assertWithMessage(errMsg).that(value2).isNull();
+ } else {
+ assertWithMessage(errMsg).that(value1.length).isEqualTo(value2.length);
+ for (int i = 0; i < value1.length; ++i) {
+ assertWithMessage(errMsg).that(value1[i]).isEqualTo(value2[i]);
+ }
+ }
+ }
+
+ public static void verifySameCredentialModels(@NonNull CredentialModel model1,
+ @NonNull CredentialModel model2) {
+
+ assertThat(model1.getUserId()).isEqualTo(model2.getUserId());
+ assertThat(model1.getSensorId()).isEqualTo(model2.getSensorId());
+ assertThat(model1.getChallenge()).isEqualTo(model2.getChallenge());
+ assertThat(model1.getGkPwHandle()).isEqualTo(model2.getGkPwHandle());
+
+ final byte[] token1 = model1.getToken();
+ final byte[] token2 = model2.getToken();
+ if (token1 == null) {
+ assertThat(token2).isNull();
+ } else {
+ assertThat(token2).isNotNull();
+ assertThat(token1.length).isEqualTo(token2.length);
+ for (int i = 0; i < token1.length; ++i) {
+ assertThat(token1[i]).isEqualTo(token2[i]);
+ }
+ }
+
+ final Bundle bundle1 = model1.getBundle();
+ final Bundle bundle2 = model2.getBundle();
+ final Set<String> keySet1 = bundle1.keySet();
+ assertThat(keySet1.equals(bundle2.keySet())).isTrue();
+ checkBundleIntValue(bundle1, bundle2, Intent.EXTRA_USER_ID);
+ checkBundleIntValue(bundle1, bundle2, EXTRA_KEY_SENSOR_ID);
+ checkBundleLongValue(bundle1, bundle2, EXTRA_KEY_CHALLENGE);
+ checkBundleByteArrayValue(bundle1, bundle2, EXTRA_KEY_CHALLENGE);
+ checkBundleLongValue(bundle1, bundle2, EXTRA_KEY_GK_PW_HANDLE);
+ }
+
+ @Test
+ public void sameValueFromBundle() {
+ final Bundle bundle = newCredentialModelIntentExtras(1234, 6677L, 1,
+ new byte[] { 33, 44, 55 }, 987654321);
+
+ final CredentialModel model1 = new CredentialModel(bundle, mClock);
+ final CredentialModel model2 = new CredentialModel(model1.getBundle(), mClock);
+
+ verifySameCredentialModels(model1, model2);
+ }
+
+ @Test
+ public void sameValueFromBundle_nullToken() {
+ final Bundle bundle = newCredentialModelIntentExtras(22, 33L, 1, null, 21L);
+
+ final CredentialModel model1 = new CredentialModel(bundle, mClock);
+ final CredentialModel model2 = new CredentialModel(model1.getBundle(), mClock);
+
+ verifySameCredentialModels(model1, model2);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java
index 7a13875..3abbca6 100644
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java
+++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java
@@ -24,12 +24,24 @@
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_SENSOR_ID;
import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_CHALLENGE;
+import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_GK_PW_HANDLE;
import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_SENSOR_ID;
+import static com.android.settings.biometrics2.ui.model.CredentialModel.isValidGkPwHandle;
+import static com.android.settings.biometrics2.ui.model.CredentialModel.isValidToken;
+import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newCredentialModelIntentExtras;
+import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newGkPwHandleCredentialIntentExtras;
+import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newInvalidChallengeCredentialIntentExtras;
+import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newValidTokenCredentialIntentExtras;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK;
+import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_IS_GENERATING_CHALLENGE;
+import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_VALID;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CredentialAction;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.GenerateChallengeCallback;
+import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.KEY_CREDENTIAL_MODEL;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN;
+import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE;
import static com.google.common.truth.Truth.assertThat;
@@ -38,20 +50,17 @@
import android.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
-import android.os.SystemClock;
+import android.os.Bundle;
import android.os.UserHandle;
import androidx.activity.result.ActivityResult;
import androidx.annotation.Nullable;
-import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.VerifyCredentialResponse;
-import com.android.settings.biometrics2.ui.model.CredentialModel;
import com.android.settings.password.ChooseLockPattern;
-import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.InstantTaskExecutorRule;
import org.junit.Before;
@@ -68,248 +77,326 @@
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
- @Mock private LifecycleOwner mLifecycleOwner;
@Mock private LockPatternUtils mLockPatternUtils;
private TestChallengeGenerator mChallengeGenerator = null;
- private AutoCredentialViewModel mAutoCredentialViewModel;
+ private AutoCredentialViewModel mViewModel;
@Before
public void setUp() {
mChallengeGenerator = new TestChallengeGenerator();
- mAutoCredentialViewModel = new AutoCredentialViewModel(
+ mViewModel = new AutoCredentialViewModel(
ApplicationProvider.getApplicationContext(),
mLockPatternUtils,
mChallengeGenerator);
}
- private CredentialModel newCredentialModel(int userId, long challenge,
- @Nullable byte[] token, long gkPwHandle) {
- final Intent intent = new Intent();
- intent.putExtra(Intent.EXTRA_USER_ID, userId);
- intent.putExtra(EXTRA_KEY_SENSOR_ID, 1);
- intent.putExtra(EXTRA_KEY_CHALLENGE, challenge);
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
- return new CredentialModel(intent, SystemClock.elapsedRealtimeClock());
- }
-
- private CredentialModel newValidTokenCredentialModel(int userId) {
- return newCredentialModel(userId, 1L, new byte[] { 0 }, 0L);
- }
-
- private CredentialModel newInvalidChallengeCredentialModel(int userId) {
- return newCredentialModel(userId, INVALID_CHALLENGE, null, 0L);
- }
-
- private CredentialModel newGkPwHandleCredentialModel(int userId, long gkPwHandle) {
- return newCredentialModel(userId, INVALID_CHALLENGE, null, gkPwHandle);
- }
-
- private void verifyNothingHappen() {
- assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull();
- }
-
- private void verifyOnlyActionLiveData(@CredentialAction int action) {
- final Integer value = mAutoCredentialViewModel.getActionLiveData().getValue();
- assertThat(value).isEqualTo(action);
- }
-
- private void setupGenerateTokenFlow(long gkPwHandle, int userId, int newSensorId,
- long newChallenge) {
+ private void setupGenerateChallenge(int userId, int newSensorId, long newChallenge) {
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
mChallengeGenerator.mUserId = userId;
mChallengeGenerator.mSensorId = newSensorId;
mChallengeGenerator.mChallenge = newChallenge;
- when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId))
- .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 }));
}
@Test
- public void checkCredential_validCredentialCase() {
+ public void testSetCredentialModel_sameResultFromSavedInstanceOrIntent() {
+ final Bundle extras = newCredentialModelIntentExtras(12, 33, 1, new byte[] { 2, 3 }, 3L);
+
+ AutoCredentialViewModel viewModel2 = new AutoCredentialViewModel(
+ ApplicationProvider.getApplicationContext(),
+ mLockPatternUtils,
+ mChallengeGenerator);
+
+ mViewModel.setCredentialModel(null, new Intent().putExtras(extras));
+ final Bundle savedInstance = new Bundle();
+ savedInstance.putBundle(KEY_CREDENTIAL_MODEL, extras);
+ viewModel2.setCredentialModel(savedInstance, new Intent());
+
+ final Bundle bundle1 = mViewModel.createCredentialIntentExtra();
+ final Bundle bundle2 = viewModel2.createCredentialIntentExtra();
+ assertThat(bundle1.getLong(EXTRA_KEY_GK_PW_HANDLE))
+ .isEqualTo(bundle2.getLong(EXTRA_KEY_GK_PW_HANDLE));
+ assertThat(bundle1.getLong(Intent.EXTRA_USER_ID))
+ .isEqualTo(bundle2.getLong(Intent.EXTRA_USER_ID));
+ assertThat(bundle1.getLong(EXTRA_KEY_CHALLENGE))
+ .isEqualTo(bundle2.getLong(EXTRA_KEY_CHALLENGE));
+ assertThat(bundle1.getInt(EXTRA_KEY_SENSOR_ID))
+ .isEqualTo(bundle2.getInt(EXTRA_KEY_SENSOR_ID));
+ final byte[] token1 = bundle1.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN);
+ final byte[] token2 = bundle2.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN);
+ assertThat(token1).isNotNull();
+ assertThat(token2).isNotNull();
+ assertThat(token1.length).isEqualTo(token2.length);
+ for (int i = 0; i < token2.length; ++i) {
+ assertThat(token1[i]).isEqualTo(token2[i]);
+ }
+ }
+
+ @Test
+ public void testSetCredentialModel_sameResultFromSavedInstanceOrIntent_invalidValues() {
+ final Bundle extras = newCredentialModelIntentExtras(UserHandle.USER_NULL,
+ INVALID_CHALLENGE, INVALID_SENSOR_ID, null, INVALID_GK_PW_HANDLE);
+
+ AutoCredentialViewModel viewModel2 = new AutoCredentialViewModel(
+ ApplicationProvider.getApplicationContext(),
+ mLockPatternUtils,
+ mChallengeGenerator);
+
+ mViewModel.setCredentialModel(null, new Intent().putExtras(extras));
+ final Bundle savedInstance = new Bundle();
+ savedInstance.putBundle(KEY_CREDENTIAL_MODEL, extras);
+ viewModel2.setCredentialModel(savedInstance, new Intent());
+
+ final Bundle bundle1 = mViewModel.createCredentialIntentExtra();
+ final Bundle bundle2 = viewModel2.createCredentialIntentExtra();
+ assertThat(bundle1.containsKey(EXTRA_KEY_GK_PW_HANDLE)).isFalse();
+ assertThat(bundle2.containsKey(EXTRA_KEY_GK_PW_HANDLE)).isFalse();
+ assertThat(bundle1.containsKey(EXTRA_KEY_CHALLENGE_TOKEN)).isFalse();
+ assertThat(bundle2.containsKey(EXTRA_KEY_CHALLENGE_TOKEN)).isFalse();
+ assertThat(bundle1.containsKey(EXTRA_KEY_SENSOR_ID)).isTrue();
+ assertThat(bundle2.containsKey(EXTRA_KEY_SENSOR_ID)).isTrue();
+ assertThat(bundle1.containsKey(Intent.EXTRA_USER_ID)).isFalse();
+ assertThat(bundle2.containsKey(Intent.EXTRA_USER_ID)).isFalse();
+ }
+
+ @Test
+ public void testCheckCredential_validCredentialCase() {
final int userId = 99;
- mAutoCredentialViewModel.setCredentialModel(newValidTokenCredentialModel(userId));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newValidTokenCredentialIntentExtras(userId)));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
// Run credential check
- mAutoCredentialViewModel.onCreate(mLifecycleOwner);
+ @CredentialAction final int action = mViewModel.checkCredential();
- verifyNothingHappen();
+ assertThat(action).isEqualTo(CREDENTIAL_VALID);
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
- public void checkCredential_needToChooseLock() {
+ public void testCheckCredential_needToChooseLock() {
final int userId = 100;
- mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId)));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_UNSPECIFIED);
// Run credential check
- mAutoCredentialViewModel.onCreate(mLifecycleOwner);
+ @CredentialAction final int action = mViewModel.checkCredential();
- verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK);
+ assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK);
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
- public void checkCredential_needToConfirmLockFoSomething() {
+ public void testCheckCredential_needToConfirmLockFoSomething() {
final int userId = 101;
- mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId)));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
// Run credential check
- mAutoCredentialViewModel.onCreate(mLifecycleOwner);
+ @CredentialAction final int action = mViewModel.checkCredential();
- verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
+ assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
- public void checkCredential_needToConfirmLockForNumeric() {
+ public void testCheckCredential_needToConfirmLockForNumeric() {
final int userId = 102;
- mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId)));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_NUMERIC);
// Run credential check
- mAutoCredentialViewModel.onCreate(mLifecycleOwner);
+ @CredentialAction final int action = mViewModel.checkCredential();
- verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
+ assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
- public void checkCredential_needToConfirmLockForAlphabetic() {
+ public void testCheckCredential_needToConfirmLockForAlphabetic() {
final int userId = 103;
- mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId)));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_ALPHABETIC);
// Run credential check
- mAutoCredentialViewModel.onCreate(mLifecycleOwner);
+ @CredentialAction final int action = mViewModel.checkCredential();
- verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
+ assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
- public void checkCredential_generateChallenge() {
+ public void testCheckCredential_generateChallenge() {
final int userId = 104;
final long gkPwHandle = 1111L;
- final CredentialModel credentialModel = newGkPwHandleCredentialModel(userId, gkPwHandle);
- mAutoCredentialViewModel.setCredentialModel(credentialModel);
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle)));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
final int newSensorId = 10;
final long newChallenge = 20L;
- setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge);
+ setupGenerateChallenge(userId, newSensorId, newChallenge);
+ when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId))
+ .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 }));
// Run credential check
- mAutoCredentialViewModel.onCreate(mLifecycleOwner);
+ @CredentialAction final int action = mViewModel.checkCredential();
- assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull();
- assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId);
- assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge);
- assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue();
- assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse();
+ assertThat(action).isEqualTo(CREDENTIAL_IS_GENERATING_CHALLENGE);
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
+ final Bundle extras = mViewModel.createCredentialIntentExtra();
+ assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId);
+ assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge);
+ assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue();
+ assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse();
assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1);
}
@Test
- public void testGetUserId() {
+ public void testCheckCredential_generateChallengeFail() {
+ final int userId = 104;
+ final long gkPwHandle = 1111L;
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle)));
+ when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
+ PASSWORD_QUALITY_SOMETHING);
+
+ final int newSensorId = 10;
+ final long newChallenge = 20L;
+ setupGenerateChallenge(userId, newSensorId, newChallenge);
+ when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId))
+ .thenReturn(newBadCredential(0));
+
+ // Run credential check
+ @CredentialAction final int action = mViewModel.checkCredential();
+
+ assertThat(action).isEqualTo(CREDENTIAL_IS_GENERATING_CHALLENGE);
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isTrue();
+ assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1);
+ }
+
+ @Test
+ public void testGetUserId_fromIntent() {
final int userId = 106;
- mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId)));
// Get userId
- assertThat(mAutoCredentialViewModel.getUserId()).isEqualTo(userId);
+ assertThat(mViewModel.getUserId()).isEqualTo(userId);
+ }
+
+ @Test
+ public void testGetUserId_fromSavedInstance() {
+ final int userId = 106;
+ final Bundle savedInstance = new Bundle();
+ savedInstance.putBundle(KEY_CREDENTIAL_MODEL,
+ newInvalidChallengeCredentialIntentExtras(userId));
+ mViewModel.setCredentialModel(savedInstance, new Intent());
+
+ // Get userId
+ assertThat(mViewModel.getUserId()).isEqualTo(userId);
}
@Test
public void testCheckNewCredentialFromActivityResult_invalidChooseLock() {
final int userId = 107;
final long gkPwHandle = 3333L;
- mAutoCredentialViewModel.setCredentialModel(
- newGkPwHandleCredentialModel(userId, gkPwHandle));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle)));
final Intent intent = new Intent();
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
+ intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
// run checkNewCredentialFromActivityResult()
- final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true,
+ final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true,
new ActivityResult(ChooseLockPattern.RESULT_FINISHED + 1, intent));
assertThat(ret).isFalse();
- verifyNothingHappen();
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
public void testCheckNewCredentialFromActivityResult_invalidConfirmLock() {
final int userId = 107;
final long gkPwHandle = 3333L;
- mAutoCredentialViewModel.setCredentialModel(
- newGkPwHandleCredentialModel(userId, gkPwHandle));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle)));
final Intent intent = new Intent();
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
+ intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
// run checkNewCredentialFromActivityResult()
- final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false,
+ final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false,
new ActivityResult(Activity.RESULT_OK + 1, intent));
assertThat(ret).isFalse();
- verifyNothingHappen();
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
public void testCheckNewCredentialFromActivityResult_nullDataChooseLock() {
final int userId = 108;
final long gkPwHandle = 4444L;
- mAutoCredentialViewModel.setCredentialModel(
- newGkPwHandleCredentialModel(userId, gkPwHandle));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle)));
// run checkNewCredentialFromActivityResult()
- final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true,
+ final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true,
new ActivityResult(ChooseLockPattern.RESULT_FINISHED, null));
assertThat(ret).isFalse();
- verifyNothingHappen();
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
public void testCheckNewCredentialFromActivityResult_nullDataConfirmLock() {
final int userId = 109;
- mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId)));
// run checkNewCredentialFromActivityResult()
- final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false,
+ final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false,
new ActivityResult(Activity.RESULT_OK, null));
assertThat(ret).isFalse();
- verifyNothingHappen();
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
}
@Test
public void testCheckNewCredentialFromActivityResult_validChooseLock() {
final int userId = 108;
- final CredentialModel credentialModel = newInvalidChallengeCredentialModel(userId);
- mAutoCredentialViewModel.setCredentialModel(credentialModel);
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId)));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
final long gkPwHandle = 6666L;
final int newSensorId = 50;
final long newChallenge = 60L;
- setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge);
- final Intent intent = new Intent();
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
+ setupGenerateChallenge(userId, newSensorId, newChallenge);
+ when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId))
+ .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 }));
// Run checkNewCredentialFromActivityResult()
- final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true,
+ final Intent intent = new Intent().putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
+ final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true,
new ActivityResult(ChooseLockPattern.RESULT_FINISHED, intent));
assertThat(ret).isTrue();
- assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull();
- assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId);
- assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge);
- assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue();
- assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse();
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
+ final Bundle extras = mViewModel.createCredentialIntentExtra();
+ assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId);
+ assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge);
+ assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue();
+ assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse();
assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1);
}
@@ -317,28 +404,30 @@
@Test
public void testCheckNewCredentialFromActivityResult_validConfirmLock() {
final int userId = 109;
- final CredentialModel credentialModel = newInvalidChallengeCredentialModel(userId);
- mAutoCredentialViewModel.setCredentialModel(credentialModel);
+ mViewModel.setCredentialModel(null,
+ new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId)));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
final long gkPwHandle = 5555L;
final int newSensorId = 80;
final long newChallenge = 90L;
- setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge);
- final Intent intent = new Intent();
- intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
+ setupGenerateChallenge(userId, newSensorId, newChallenge);
+ when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId))
+ .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 }));
// Run checkNewCredentialFromActivityResult()
- final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false,
+ final Intent intent = new Intent().putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
+ final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false,
new ActivityResult(Activity.RESULT_OK, intent));
assertThat(ret).isTrue();
- assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull();
- assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId);
- assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge);
- assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue();
- assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse();
+ assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull();
+ final Bundle extras = mViewModel.createCredentialIntentExtra();
+ assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId);
+ assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge);
+ assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue();
+ assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse();
assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1);
}
@@ -377,4 +466,12 @@
.setGatekeeperHAT(hat)
.build();
}
+
+ private VerifyCredentialResponse newBadCredential(int timeout) {
+ if (timeout > 0) {
+ return VerifyCredentialResponse.fromTimeout(timeout);
+ } else {
+ return VerifyCredentialResponse.fromError();
+ }
+ }
}
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java
index 5069ea1..a9536cf 100644
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java
+++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java
@@ -46,6 +46,7 @@
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.MutableLiveData;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -93,6 +94,18 @@
}
@Test
+ public void testClearActionLiveData() {
+ final MutableLiveData<Integer> actionLiveData =
+ (MutableLiveData<Integer>) mViewModel.getActionLiveData();
+ actionLiveData.postValue(1);
+ assertThat(actionLiveData.getValue()).isEqualTo(1);
+
+ mViewModel.clearActionLiveData();
+
+ assertThat(actionLiveData.getValue()).isNull();
+ }
+
+ @Test
public void testGetEnrollmentRequest() {
final EnrollmentRequest request = newAllFalseRequest(mApplication);
@@ -202,11 +215,13 @@
@Test
public void testSetHasScrolledToBottom() {
- mViewModel.setHasScrolledToBottom();
-
+ mViewModel.setHasScrolledToBottom(true);
FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue();
-
assertThat(status.hasScrollToBottom()).isEqualTo(true);
+
+ mViewModel.setHasScrolledToBottom(false);
+ status = mViewModel.getPageStatusLiveData().getValue();
+ assertThat(status.hasScrollToBottom()).isEqualTo(false);
}
@Test
diff --git a/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java b/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java
index e6df8a0..3fe6882 100644
--- a/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java
+++ b/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java
@@ -16,6 +16,8 @@
package com.android.settings.network;
+import static com.android.settings.network.InternetResetHelper.RESTART_TIMEOUT_MS;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -29,8 +31,6 @@
import android.content.Context;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.HandlerThread;
import android.os.Looper;
import androidx.lifecycle.Lifecycle;
@@ -39,7 +39,6 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.android.settingslib.connectivity.ConnectivitySubsystemsRecoveryManager;
import com.android.settingslib.utils.HandlerInjector;
import org.junit.Before;
@@ -47,6 +46,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -55,66 +55,46 @@
@Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Spy
+ private final Context mContext = ApplicationProvider.getApplicationContext();
@Mock
private WifiManager mWifiManager;
@Mock
- public HandlerThread mWorkerThread;
+ InternetResetHelper.RecoveryWorker mRecoveryWorker;
@Mock
- public ConnectivitySubsystemsRecoveryManager mConnectivitySubsystemsRecoveryManager;
+ HandlerInjector mHandlerInjector;
@Mock
public NetworkMobileProviderController mMobileNetworkController;
- private Context mContext;
private InternetResetHelper mInternetResetHelper;
private Preference mResettingPreference;
private Preference mWifiTogglePreferences;
private PreferenceCategory mConnectedWifiEntryPreferences;
+ private PreferenceCategory mFirstWifiEntryPreference;
private PreferenceCategory mWifiEntryPreferences;
- private FakeHandlerInjector mFakeHandlerInjector;
-
- private static class FakeHandlerInjector extends HandlerInjector {
-
- private Runnable mRunnable;
-
- FakeHandlerInjector(Handler handler) {
- super(handler);
- }
-
- @Override
- public void postDelayed(Runnable runnable, long delayMillis) {
- mRunnable = runnable;
- }
-
- public Runnable getRunnable() {
- return mRunnable;
- }
- }
-
@Before
public void setUp() {
- mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+ when(mRecoveryWorker.isRecovering()).thenReturn(false);
if (Looper.myLooper() == null) {
Looper.prepare();
}
- mResettingPreference = new Preference(mContext);
+ mResettingPreference = spy(new Preference(mContext));
mWifiTogglePreferences = new Preference(mContext);
mConnectedWifiEntryPreferences = spy(new PreferenceCategory(mContext));
+ mFirstWifiEntryPreference = spy(new PreferenceCategory(mContext));
mWifiEntryPreferences = spy(new PreferenceCategory(mContext));
- final Lifecycle lifecycle = mock(Lifecycle.class);
- mInternetResetHelper = new InternetResetHelper(mContext, lifecycle);
- mInternetResetHelper.mWorkerThread = mWorkerThread;
- mFakeHandlerInjector = new FakeHandlerInjector(mContext.getMainThreadHandler());
- mInternetResetHelper.mHandlerInjector = mFakeHandlerInjector;
- mInternetResetHelper.mConnectivitySubsystemsRecoveryManager =
- mConnectivitySubsystemsRecoveryManager;
- mInternetResetHelper.setResettingPreference(mResettingPreference);
- mInternetResetHelper.setMobileNetworkController(mMobileNetworkController);
- mInternetResetHelper.setWifiTogglePreference(mWifiTogglePreferences);
- mInternetResetHelper.addWifiNetworkPreference(mConnectedWifiEntryPreferences);
- mInternetResetHelper.addWifiNetworkPreference(mWifiEntryPreferences);
+ mInternetResetHelper = new InternetResetHelper(mContext, mock(Lifecycle.class),
+ mMobileNetworkController,
+ mWifiTogglePreferences,
+ mConnectedWifiEntryPreferences,
+ mFirstWifiEntryPreference,
+ mWifiEntryPreferences,
+ mResettingPreference);
+ mInternetResetHelper.mHandlerInjector = mHandlerInjector;
+ mInternetResetHelper.mRecoveryWorker = mRecoveryWorker;
}
@Test
@@ -135,30 +115,10 @@
}
@Test
- public void onDestroy_quitWorkerThread() {
+ public void onDestroy_removeCallbacks() {
mInternetResetHelper.onDestroy();
- verify(mWorkerThread).quit();
- }
-
- @Test
- public void onSubsystemRestartOperationEnd_recoveryIsNotReady_postResumeRunnable() {
- mInternetResetHelper.mIsRecoveryReady = false;
-
- mInternetResetHelper.onSubsystemRestartOperationEnd();
-
- assertThat(mInternetResetHelper.mIsRecoveryReady).isTrue();
- assertThat(mFakeHandlerInjector.getRunnable())
- .isEqualTo(mInternetResetHelper.mResumeRunnable);
- }
-
- @Test
- public void onSubsystemRestartOperationEnd_recoveryIsReady_doNothing() {
- mInternetResetHelper.mIsRecoveryReady = true;
-
- mInternetResetHelper.onSubsystemRestartOperationEnd();
-
- assertThat(mFakeHandlerInjector.getRunnable()).isNull();
+ verify(mHandlerInjector).removeCallbacks(any());
}
@Test
@@ -169,19 +129,16 @@
mInternetResetHelper.updateWifiStateChange();
assertThat(mInternetResetHelper.mIsWifiReady).isFalse();
- assertThat(mFakeHandlerInjector.getRunnable()).isNull();
}
@Test
- public void updateWifiStateChange_wifiIsNotReadyAndWifiEnabled_postResumeRunnable() {
+ public void updateWifiStateChange_wifiIsNotReadyAndWifiEnabled_updateWifiIsReady() {
mInternetResetHelper.mIsWifiReady = false;
when(mWifiManager.isWifiEnabled()).thenReturn(true);
mInternetResetHelper.updateWifiStateChange();
assertThat(mInternetResetHelper.mIsWifiReady).isTrue();
- assertThat(mFakeHandlerInjector.getRunnable())
- .isEqualTo(mInternetResetHelper.mResumeRunnable);
}
@Test
@@ -191,7 +148,6 @@
mInternetResetHelper.updateWifiStateChange();
assertThat(mInternetResetHelper.mIsWifiReady).isTrue();
- assertThat(mFakeHandlerInjector.getRunnable()).isNull();
}
@Test
@@ -203,16 +159,15 @@
// Hide subsystem preferences
verify(mMobileNetworkController).hidePreference(true /* hide */, true /* immediately*/);
assertThat(mWifiTogglePreferences.isVisible()).isFalse();
- verify(mConnectedWifiEntryPreferences).removeAll();
assertThat(mConnectedWifiEntryPreferences.isVisible()).isFalse();
- verify(mWifiEntryPreferences).removeAll();
+ assertThat(mFirstWifiEntryPreference.isVisible()).isFalse();
assertThat(mWifiEntryPreferences.isVisible()).isFalse();
}
@Test
public void resumePreferences_onlyRecoveryReady_shouldShowSubSysHideResetting() {
mInternetResetHelper.suspendPreferences();
- mInternetResetHelper.mIsRecoveryReady = true;
+ when(mRecoveryWorker.isRecovering()).thenReturn(false);
mInternetResetHelper.mIsWifiReady = false;
mInternetResetHelper.resumePreferences();
@@ -224,13 +179,14 @@
// Hide Wi-Fi preferences
assertThat(mWifiTogglePreferences.isVisible()).isFalse();
assertThat(mConnectedWifiEntryPreferences.isVisible()).isFalse();
+ assertThat(mFirstWifiEntryPreference.isVisible()).isFalse();
assertThat(mWifiEntryPreferences.isVisible()).isFalse();
}
@Test
public void resumePreferences_onlyWifiReady_shouldShowSubSysHideResetting() {
mInternetResetHelper.suspendPreferences();
- mInternetResetHelper.mIsRecoveryReady = false;
+ when(mRecoveryWorker.isRecovering()).thenReturn(true);
mInternetResetHelper.mIsWifiReady = true;
mInternetResetHelper.resumePreferences();
@@ -240,6 +196,7 @@
// Show Wi-Fi preferences
assertThat(mWifiTogglePreferences.isVisible()).isTrue();
assertThat(mConnectedWifiEntryPreferences.isVisible()).isTrue();
+ assertThat(mFirstWifiEntryPreference.isVisible()).isTrue();
assertThat(mWifiEntryPreferences.isVisible()).isTrue();
// Hide Mobile Network controller
verify(mMobileNetworkController, never())
@@ -249,14 +206,16 @@
@Test
public void resumePreferences_allReady_shouldShowSubSysHideResetting() {
mInternetResetHelper.suspendPreferences();
- mInternetResetHelper.mIsRecoveryReady = true;
+ when(mRecoveryWorker.isRecovering()).thenReturn(false);
mInternetResetHelper.mIsWifiReady = true;
+
mInternetResetHelper.resumePreferences();
// Show subsystem preferences
verify(mMobileNetworkController).hidePreference(false, true);
assertThat(mWifiTogglePreferences.isVisible()).isTrue();
assertThat(mConnectedWifiEntryPreferences.isVisible()).isTrue();
+ assertThat(mFirstWifiEntryPreference.isVisible()).isTrue();
assertThat(mWifiEntryPreferences.isVisible()).isTrue();
// Hide resetting preference
assertThat(mResettingPreference.isVisible()).isFalse();
@@ -264,22 +223,39 @@
@Test
public void restart_recoveryNotAvailable_shouldDoTriggerSubsystemRestart() {
- when(mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()).thenReturn(false);
+ when(mRecoveryWorker.isRecoveryAvailable()).thenReturn(false);
mInternetResetHelper.restart();
- verify(mConnectivitySubsystemsRecoveryManager, never())
- .triggerSubsystemRestart(any(), any());
+ verify(mRecoveryWorker, never()).triggerRestart();
}
@Test
public void restart_recoveryAvailable_triggerSubsystemRestart() {
- when(mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()).thenReturn(true);
+ when(mRecoveryWorker.isRecoveryAvailable()).thenReturn(true);
mInternetResetHelper.restart();
- assertThat(mFakeHandlerInjector.getRunnable())
- .isEqualTo(mInternetResetHelper.mTimeoutRunnable);
- verify(mConnectivitySubsystemsRecoveryManager).triggerSubsystemRestart(any(), any());
+ verify(mHandlerInjector)
+ .postDelayed(mInternetResetHelper.mTimeoutRunnable, RESTART_TIMEOUT_MS);
+ verify(mRecoveryWorker).triggerRestart();
+ }
+
+ @Test
+ public void checkRecovering_isRecovering_showResetting() {
+ when(mRecoveryWorker.isRecovering()).thenReturn(true);
+
+ mInternetResetHelper.checkRecovering();
+
+ verify(mResettingPreference).setVisible(true);
+ }
+
+ @Test
+ public void checkRecovering_isNotRecovering_doNotShowResetting() {
+ when(mRecoveryWorker.isRecovering()).thenReturn(false);
+
+ mInternetResetHelper.checkRecovering();
+
+ verify(mResettingPreference, never()).setVisible(true);
}
}
diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
index 45f3693..16e3963 100644
--- a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
@@ -28,18 +28,24 @@
import android.app.Instrumentation;
import android.content.Context;
+import android.os.Looper;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.settings.testutils.ResourcesUtils;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
+import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
import org.junit.Before;
import org.junit.Test;
@@ -49,6 +55,10 @@
@RunWith(AndroidJUnit4.class)
public class MobileDataPreferenceControllerTest {
+ private static final String SUB_ID_1 = "1";
+ private static final String SUB_ID_2 = "2";
+ private static final String DISPLAY_NAME_1 = "Sub 1";
+ private static final String DISPLAY_NAME_2 = "Sub 2";
private static final int SUB_ID = 2;
private static final int SUB_ID_OTHER = 3;
@@ -64,7 +74,15 @@
private SubscriptionInfo mSubscriptionInfo;
@Mock
private FragmentTransaction mFragmentTransaction;
-
+ @Mock
+ private Lifecycle mLifecycle;
+ @Mock
+ private LifecycleOwner mLifecycleOwner;
+ private SubscriptionInfoEntity mSubInfo1;
+ private SubscriptionInfoEntity mSubInfo2;
+ private MobileNetworkInfoEntity mNetworkInfo1;
+ private MobileNetworkInfoEntity mNetworkInfo2;
+ private LifecycleRegistry mLifecycleRegistry;
private MobileDataPreferenceController mController;
private SwitchPreference mPreference;
private Context mContext;
@@ -73,6 +91,10 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
mContext = spy(ApplicationProvider.getApplicationContext());
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
@@ -83,22 +105,45 @@
doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
mPreference = new SwitchPreference(mContext);
- mController = new MobileDataPreferenceController(mContext, "mobile_data");
- mController.init(mFragmentManager, SUB_ID);
+ mController = new MobileDataPreferenceController(mContext, "mobile_data", mLifecycle,
+ mLifecycleOwner, SUB_ID);
+ mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1);
mPreference.setKey(mController.getPreferenceKey());
+ mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
+ when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
+ }
+
+ private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, String displayName,
+ boolean isOpportunistic, boolean isValid, boolean isActive, boolean isAvailable,
+ boolean isDefaultData) {
+ int id = Integer.parseInt(subId);
+ return new SubscriptionInfoEntity(subId, id, id,
+ displayName, displayName, 0, "mcc", "mnc", "countryIso", false, id,
+ TelephonyManager.DEFAULT_PORT_INDEX, isOpportunistic, null,
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, displayName, false,
+ "1234567890", true, "default", false, isValid, true, isActive, isAvailable, false,
+ false, isDefaultData, false, false);
+ }
+
+ private MobileNetworkInfoEntity setupMobileNetworkInfoEntity(String subId,
+ boolean isDatEnabled) {
+ return new MobileNetworkInfoEntity(subId, false, false, isDatEnabled, false, false, false,
+ false, false, false, false, false);
}
@Test
public void getAvailabilityStatus_invalidSubscription_returnAvailableUnsearchable() {
- mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID, mSubInfo1,
+ mNetworkInfo1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
public void isDialogNeeded_disableSingleSim_returnFalse() {
- doReturn(true).when(mTelephonyManager).isDataEnabled();
- doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+ mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true,
+ true);
+ mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
doReturn(1).when(mTelephonyManager).getActiveModemCount();
assertThat(mController.isDialogNeeded()).isFalse();
@@ -106,12 +151,15 @@
@Test
public void isDialogNeeded_enableNonDefaultSimInMultiSimMode_returnTrue() {
- doReturn(false).when(mTelephonyManager).isDataEnabled();
- doReturn(mSubscriptionInfo).when(mSubscriptionManager)
- .getActiveSubscriptionInfo(SUB_ID);
+ mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true,
+ false);
+ mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
+ doReturn(1).when(mTelephonyManager).getActiveModemCount();
// Ideally, it would be better if we could set the default data subscription to
// SUB_ID_OTHER, and set that as an active subscription id.
- when(mSubscriptionManager.isActiveSubscriptionId(anyInt())).thenReturn(true);
+ mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, false, true, true, true,
+ true);
+ mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
doReturn(2).when(mTelephonyManager).getActiveModemCount();
assertThat(mController.isDialogNeeded()).isTrue();
@@ -132,8 +180,11 @@
@Test
public void onPreferenceChange_singleSim_On_shouldEnableData() {
- doReturn(true).when(mTelephonyManager).isDataEnabled();
- doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+ mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true,
+ true);
+ mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
+ mController.setSubscriptionInfoEntity(mSubInfo1);
+ mController.setMobileNetworkInfoEntity(mNetworkInfo1);
doReturn(1).when(mTelephonyManager).getActiveModemCount();
mController.onPreferenceChange(mPreference, true);
@@ -143,8 +194,11 @@
@Test
public void onPreferenceChange_multiSim_On_shouldEnableData() {
- doReturn(true).when(mTelephonyManager).isDataEnabled();
- doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+ mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true,
+ true);
+ mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
+ mController.setSubscriptionInfoEntity(mSubInfo1);
+ mController.setMobileNetworkInfoEntity(mNetworkInfo1);
doReturn(2).when(mTelephonyManager).getActiveModemCount();
mController.onPreferenceChange(mPreference, true);
@@ -154,18 +208,20 @@
@Test
public void isChecked_returnUserDataEnabled() {
- mController.init(mFragmentManager, SUB_ID);
+ mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false);
+ mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1);
assertThat(mController.isChecked()).isFalse();
- doReturn(true).when(mTelephonyManager).isDataEnabled();
+ mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true);
+ mController.setMobileNetworkInfoEntity(mNetworkInfo1);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void updateState_opportunistic_disabled() {
- doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
- mController.init(mFragmentManager, SUB_ID);
- doReturn(true).when(mSubscriptionInfo).isOpportunistic();
+ mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true,
+ true);
+ mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1);
mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isFalse();
@@ -176,9 +232,9 @@
@Test
public void updateState_notOpportunistic_enabled() {
- doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
- mController.init(mFragmentManager, SUB_ID);
- doReturn(false).when(mSubscriptionInfo).isOpportunistic();
+ mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true,
+ true);
+ mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1);
mController.updateState(mPreference);
assertThat(mPreference.isEnabled()).isTrue();