Snap for 11420186 from ca4565083f89c2bf5b0757a726bbb6f04093ecce to 24Q2-release
Change-Id: I8313be7be164bd6b6f9de9e4290a5765681d1f54
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 96b798a..e4ed275 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -802,6 +802,11 @@
</intent-filter>
</activity>
+ <activity android:name=".network.SimOnboardingActivity"
+ android:exported="false"
+ android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
+ android:theme="@style/Theme.SpaLib.BottomSheetDialog"/>
+
<activity android:name=".network.telephony.ToggleSubscriptionDialogActivity"
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
@@ -4404,9 +4409,12 @@
<activity android:name=".applications.credentials.CredentialsPickerActivity"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
- android:exported="false">
- <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.applications.credentials.DefaultCombinedPicker" />
+ android:exported="true">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.REQUEST_SET_AUTOFILL_SERVICE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="package" />
+ </intent-filter>
</activity>
<activity
@@ -4551,19 +4559,6 @@
android:exported="false">
</activity>
- <activity android:name=".applications.autofill.AutofillPickerTrampolineActivity"
- android:theme="@android:style/Theme.NoDisplay"
- android:excludeFromRecents="true"
- android:launchMode="singleInstance"
- android:exported="true"
- android:label="@string/autofill_app">
- <intent-filter android:priority="1">
- <action android:name="android.settings.REQUEST_SET_AUTOFILL_SERVICE" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:scheme="package" />
- </intent-filter>
- </activity>
-
<activity android:name="Settings$AdvancedConnectedDeviceActivity"
android:exported="true"
android:label="@string/connected_device_connections_title">
diff --git a/res/values/config.xml b/res/values/config.xml
index 433620d..9d71671 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -709,7 +709,7 @@
<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">true</bool>
+ <bool name="config_app_battery_usage_list_enabled">false</bool>
<!-- Whether sim related information is visible to the end user. -->
<bool name="config_show_sim_info">true</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 965daf6..7291fad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1269,7 +1269,7 @@
<!-- Header in hide Private Space settings page to access Private Space when hidden. [CHAR LIMIT=60] -->
<string name="privatespace_access_header">Access private space when hidden</string>
<!-- Text in hide Private Space settings page on how to search Private Space when hidden. [CHAR LIMIT=60] -->
- <string name="privatespace_search_description">From your apps list, enter \'private space\' in the search bar</string>
+ <string name="privatespace_search_description">From your apps list, enter \"private space\" in the search bar</string>
<!-- Text in hide Private Space settings page to tap on Private Space tile. [CHAR LIMIT=60] -->
<string name="privatespace_tap_tile_description">Tap the private space tile</string>
<!-- Text in hide Private Space settings page to Unlock Private Space. [CHAR LIMIT=60] -->
@@ -1373,18 +1373,6 @@
<!-- Header for private space choose your pattern screen [CHAR LIMIT=40] -->
<string name="private_space_choose_your_pattern_header">Set a pattern for your private space</string>
- <!-- TODO(b/309950257): Remove below strings once QSTIle fulfillment is complete. -->
- <!-- Header in hide Private Space settings page to unhide Private Space. [CHAR LIMIT=90] -->
- <string name="privatespace_unhide_header">To show private space (Not final UX)</string>
- <!-- Text in hide Private Space settings page on how to open Private Space setting. [CHAR LIMIT=NONE] -->
- <string name="privatespace_open_settings">Open the Settings App</string>
- <!-- Text in hide Private Space settings page on how to open Private Space setting. [CHAR LIMIT=NONE] -->
- <string name="privatespace_tap_settings">Tap on Security & privacy > private space > Hide private space when locked</string>
- <!-- Text in hide Private Space settings page to off hide toggle. [CHAR LIMIT=90] -->
- <string name="privatespace_turnoff_hide">Turn off \‘Hide private space when locked\’ toggle</string>
- <!-- Note in hide Private Space settings page to inform that this is a development feature. [CHAR LIMIT=NONE] -->
- <string name="privatespace_development_note">Note to Googlers: The development of this feature is still in progress</string>
-
<!-- Text shown when "Add fingerprint" button is disabled -->
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
<!-- Text shown when users has enrolled a maximum number of fingerprints [CHAR LIMIT=NONE] -->
@@ -7318,7 +7306,7 @@
<!-- Title for setting tile leading to saved autofill passwords, autofill, and account settings [CHAR LIMIT=40]-->
<string name="account_dashboard_title">Passwords & accounts</string>
<!-- Summary for setting tile leading to saved autofill passwords, autofill, and account settings [CHAR LIMIT=NONE]-->
- <string name="account_dashboard_default_summary">Saved passwords, autofill, synced accounts</string>
+ <string name="account_dashboard_default_summary">Suggestions for sign-in & autofill</string>
<!-- Title for setting tile leading to setting UI which allows user set default app to
handle actions such as open web page, making phone calls, default SMS apps [CHAR LIMIT=40]-->
<string name="app_default_dashboard_title">Default apps</string>
@@ -10785,8 +10773,8 @@
<string name="autofill_passwords">Passwords</string>
<!-- Preference category for showing autofill and credman services with saved credentials. [CHAR LIMIT=60] -->
<string name="credman_chosen_app_title">Preferred service</string>
- <!-- Preference category for showing additional credential providers. [CHAR LIMIT=60] -->
- <string name="credman_credentials">Additional providers</string>
+ <!-- Preference category for showing additional credential services. [CHAR LIMIT=60] -->
+ <string name="credman_credentials">Additional services</string>
<!-- Summary for passwords settings that shows how many passwords are saved for each autofill
service. [CHAR LIMIT=NONE] -->
<string name="autofill_passwords_count">{count, plural,
@@ -10831,7 +10819,7 @@
</string>
<!-- Title of the screen where the user picks a provider. [CHAR_LIMIT=NONE] -->
- <string name="credman_picker_title">Passwords, passkeys, and data services</string>
+ <string name="credman_picker_title">Preferred service for passwords, passkeys & autofill</string>
<!-- Title of the warning dialog for disabling the credential provider. [CHAR_LIMIT=NONE] -->
<string name="credman_confirmation_message_title">Turn off %1$s\?</string>
@@ -10848,6 +10836,9 @@
]]>
</string>
+ <!-- Title for setting tile leading to saved autofill passwords, passkeys, autofill, and account settings [CHAR LIMIT=40]-->
+ <string name="account_dashboard_title_with_passkeys">Passwords, passkeys & autofill</string>
+
<!-- Message of the warning dialog for disabling the credential provider (new strings for 24Q3). [CHAR_LIMIT=NONE] -->
<string name="credman_confirmation_message_new_ui">
<![CDATA[
@@ -12891,4 +12882,4 @@
<!-- Authority of the content provider that support methods restartPhoneProcess and restartRild. Will be overlaid by OEM.-->
<string name="reset_telephony_stack_content_provider_authority" translatable="false"></string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/res/xml/accounts_dashboard_settings_credman.xml b/res/xml/accounts_dashboard_settings_credman.xml
index 7266bda..08377c9 100644
--- a/res/xml/accounts_dashboard_settings_credman.xml
+++ b/res/xml/accounts_dashboard_settings_credman.xml
@@ -18,7 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="user_and_account_settings_screen"
- android:title="@string/account_dashboard_title"
+ android:title="@string/account_dashboard_title_with_passkeys"
settings:keywords="@string/keywords_accounts">
<PreferenceCategory
diff --git a/res/xml/accounts_personal_dashboard_settings_credman.xml b/res/xml/accounts_personal_dashboard_settings_credman.xml
index 9473e17..16ab31b 100644
--- a/res/xml/accounts_personal_dashboard_settings_credman.xml
+++ b/res/xml/accounts_personal_dashboard_settings_credman.xml
@@ -19,7 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="user_and_account_settings_screen"
- android:title="@string/account_dashboard_title"
+ android:title="@string/account_dashboard_title_with_passkeys"
settings:keywords="@string/keywords_accounts">
<PreferenceCategory
diff --git a/res/xml/accounts_private_dashboard_settings_credman.xml b/res/xml/accounts_private_dashboard_settings_credman.xml
index 54db839..c0b12b5 100644
--- a/res/xml/accounts_private_dashboard_settings_credman.xml
+++ b/res/xml/accounts_private_dashboard_settings_credman.xml
@@ -19,7 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="user_and_account_settings_screen"
- android:title="@string/account_dashboard_title"
+ android:title="@string/account_dashboard_title_with_passkeys"
settings:keywords="@string/keywords_accounts">
<PreferenceCategory
diff --git a/res/xml/accounts_work_dashboard_settings_credman.xml b/res/xml/accounts_work_dashboard_settings_credman.xml
index d649940..44bdb52 100644
--- a/res/xml/accounts_work_dashboard_settings_credman.xml
+++ b/res/xml/accounts_work_dashboard_settings_credman.xml
@@ -19,7 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="user_and_account_settings_screen"
- android:title="@string/account_dashboard_title"
+ android:title="@string/account_dashboard_title_with_passkeys"
settings:keywords="@string/keywords_accounts">
<PreferenceCategory
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index e62f5c0..1af8a8c 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
+<!-- Copyright (C) 2024 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -51,6 +51,13 @@
settings:keywords="@string/keywords_battery_saver"
settings:controller="com.android.settings.fuelgauge.BatterySaverController" />
+ <Preference
+ android:fragment="com.android.settings.fuelgauge.SmartBatterySettings"
+ android:key="smart_battery_manager"
+ android:title="@string/smart_battery_manager_title"
+ settings:controller="com.android.settings.fuelgauge.batterytip.BatteryManagerPreferenceController"
+ settings:keywords="@string/keywords_battery_adaptive_preferences" />
+
<SwitchPreferenceCompat
android:key="battery_percentage"
android:title="@string/battery_percentage"
diff --git a/res/xml/privatespace_hide_locked.xml b/res/xml/privatespace_hide_locked.xml
index f26d207..f453d75 100644
--- a/res/xml/privatespace_hide_locked.xml
+++ b/res/xml/privatespace_hide_locked.xml
@@ -34,33 +34,27 @@
android:selectable="false"
settings:searchable="false" />
- <Preference
- android:key="private_space_note"
- android:summary="@string/privatespace_development_note"
- android:selectable="false"
- settings:searchable="false" />
-
<PreferenceCategory
- android:title="@string/privatespace_unhide_header">
+ android:title="@string/privatespace_access_header">
<Preference
android:key="search_when_locked_footer"
android:icon="@drawable/counter_1_24dp"
- android:title="@string/privatespace_open_settings"
+ android:title="@string/privatespace_search_description"
android:selectable="false"
settings:searchable="false" />
<Preference
android:key="tap_tile_footer"
android:icon="@drawable/counter_2_24dp"
- android:title="@string/privatespace_tap_settings"
+ android:title="@string/privatespace_tap_tile_description"
android:selectable="false"
settings:searchable="false" />
<Preference
- android:key="turn_off_footer"
+ android:key="unlock_profile_footer"
android:icon="@drawable/counter_3_24dp"
- android:title="@string/privatespace_turnoff_hide"
+ android:title="@string/privatespace_unlock_description"
android:selectable="false"
settings:searchable="false" />
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index d050a1f..31c6af3 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -180,7 +180,7 @@
android:icon="@drawable/ic_settings_accounts"
android:key="top_level_accounts"
android:order="-10"
- android:title="@string/account_dashboard_title"
+ android:title="@string/account_dashboard_title_with_passkeys"
android:summary="@string/summary_placeholder"
settings:highlightableMenuKey="@string/menu_key_accounts"
settings:controller="com.android.settings.accounts.TopLevelAccountEntryPreferenceController"/>
diff --git a/src/com/android/settings/accessibility/HearingDevicePairingFragment.java b/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
index 78f5b4c..0b762f3 100644
--- a/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
+++ b/src/com/android/settings/accessibility/HearingDevicePairingFragment.java
@@ -17,6 +17,7 @@
package com.android.settings.accessibility;
import static android.app.Activity.RESULT_OK;
+import static android.bluetooth.BluetoothGatt.GATT_SUCCESS;
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
import android.app.settings.SettingsEnums;
@@ -191,7 +192,7 @@
public void onDeviceBondStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
int bondState) {
if (DEBUG) {
- Log.d(TAG, "onDeviceBondStateChanged: " + cachedDevice.getName() + ", state = "
+ Log.d(TAG, "onDeviceBondStateChanged: " + cachedDevice.getDevice() + ", state = "
+ bondState);
}
if (bondState == BluetoothDevice.BOND_BONDED) {
@@ -275,13 +276,13 @@
}
mDevicePreferenceMap.put(cachedDevice, preference);
if (DEBUG) {
- Log.d(TAG, "Add device. device: " + cachedDevice);
+ Log.d(TAG, "Add device. device: " + cachedDevice.getDevice());
}
}
void removeDevice(CachedBluetoothDevice cachedDevice) {
if (DEBUG) {
- Log.d(TAG, "removeDevice: " + cachedDevice);
+ Log.d(TAG, "removeDevice: " + cachedDevice.getDevice());
}
BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
if (mAvailableHearingDeviceGroup != null && preference != null) {
@@ -328,10 +329,15 @@
CachedBluetoothDevice cachedDevice = mCachedDeviceManager.findDevice(device);
if (cachedDevice == null) {
cachedDevice = mCachedDeviceManager.addDevice(device);
+ } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
+ if (DEBUG) {
+ Log.d(TAG, "Skip this device, already bonded: " + cachedDevice.getDevice());
+ }
+ return;
}
if (cachedDevice.getHearingAidInfo() == null) {
if (DEBUG) {
- Log.d(TAG, "Set hearing aid info on device: " + cachedDevice);
+ Log.d(TAG, "Set hearing aid info on device: " + cachedDevice.getDevice());
}
cachedDevice.setHearingAidInfo(new HearingAidInfo.Builder().build());
}
@@ -449,7 +455,7 @@
void discoverServices(CachedBluetoothDevice cachedDevice) {
if (DEBUG) {
- Log.d(TAG, "connectGattToCheckCompatibility, device: " + cachedDevice);
+ Log.d(TAG, "connectGattToCheckCompatibility, device: " + cachedDevice.getDevice());
}
BluetoothGatt gatt = cachedDevice.getDevice().connectGatt(getContext(), false,
new BluetoothGattCallback() {
@@ -459,26 +465,36 @@
super.onConnectionStateChange(gatt, status, newState);
if (DEBUG) {
Log.d(TAG, "onConnectionStateChange, status: " + status + ", newState: "
- + newState + ", device: " + cachedDevice);
+ + newState + ", device: " + cachedDevice.getDevice());
}
- if (newState == BluetoothProfile.STATE_CONNECTED) {
+ if (status == GATT_SUCCESS
+ && newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices();
+ } else {
+ gatt.disconnect();
+ mConnectingGattList.remove(gatt);
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
- boolean isCompatible = gatt.getService(BluetoothUuid.HEARING_AID.getUuid())
- != null
- || gatt.getService(BluetoothUuid.HAS.getUuid()) != null;
if (DEBUG) {
- Log.d(TAG,
- "onServicesDiscovered, compatible with Android: " + isCompatible
- + ", device: " + cachedDevice);
+ Log.d(TAG, "onServicesDiscovered, status: " + status + ", device: "
+ + cachedDevice.getDevice());
}
- if (isCompatible) {
- addDevice(cachedDevice);
+ if (status == GATT_SUCCESS) {
+ if (gatt.getService(BluetoothUuid.HEARING_AID.getUuid()) != null
+ || gatt.getService(BluetoothUuid.HAS.getUuid()) != null) {
+ if (DEBUG) {
+ Log.d(TAG, "compatible with Android, device: "
+ + cachedDevice.getDevice());
+ }
+ addDevice(cachedDevice);
+ }
+ } else {
+ gatt.disconnect();
+ mConnectingGattList.remove(gatt);
}
}
});
diff --git a/src/com/android/settings/applications/credentials/CombinedProviderInfo.java b/src/com/android/settings/applications/credentials/CombinedProviderInfo.java
index f8a3b0f..4f27870 100644
--- a/src/com/android/settings/applications/credentials/CombinedProviderInfo.java
+++ b/src/com/android/settings/applications/credentials/CombinedProviderInfo.java
@@ -16,6 +16,7 @@
package com.android.settings.applications.credentials;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -24,7 +25,6 @@
import android.credentials.CredentialProviderInfo;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
-import android.os.UserManager;
import android.service.autofill.AutofillServiceInfo;
import android.text.TextUtils;
import android.util.IconDrawableFactory;
@@ -49,7 +49,7 @@
private static final String TAG = "CombinedProviderInfo";
private static final String SETTINGS_ACTIVITY_INTENT_ACTION = "android.intent.action.MAIN";
private static final String SETTINGS_ACTIVITY_INTENT_CATEGORY =
- "android.intent.category.LAUNCHER";
+ "android.intent.category.DEFAULT";
private final List<CredentialProviderInfo> mCredentialProviderInfos;
private final @Nullable AutofillServiceInfo mAutofillServiceInfo;
@@ -327,10 +327,8 @@
}
public static @Nullable Intent createSettingsActivityIntent(
- @NonNull Context context,
@Nullable CharSequence packageName,
- @Nullable CharSequence settingsActivity,
- int currentUserId) {
+ @Nullable CharSequence settingsActivity) {
if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(settingsActivity)) {
return null;
}
@@ -350,19 +348,25 @@
Intent intent = new Intent(SETTINGS_ACTIVITY_INTENT_ACTION);
intent.addCategory(SETTINGS_ACTIVITY_INTENT_CATEGORY);
intent.setComponent(cn);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return intent;
+ }
- int contextUserId = context.getUser().getIdentifier();
- if (currentUserId != contextUserId && UserManager.isHeadlessSystemUserMode()) {
- Log.w(
- TAG,
- "onLeftSideClicked(): using context for current user ("
- + currentUserId
- + ") instead of user "
- + contextUserId
- + " on headless system user mode");
- context = context.createContextAsUser(UserHandle.of(currentUserId), /* flags= */ 0);
+ /** Launches the settings activity intent. */
+ public static void launchSettingsActivityIntent(
+ @NonNull Context context,
+ @Nullable CharSequence packageName,
+ @Nullable CharSequence settingsActivity,
+ int userId) {
+ Intent settingsIntent = createSettingsActivityIntent(packageName, settingsActivity);
+ if (settingsIntent == null) {
+ return;
}
- return intent;
+ try {
+ context.startActivityAsUser(settingsIntent, UserHandle.of(userId));
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Failed to open settings activity", e);
+ }
}
}
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index 4fc0e16..d98bc51 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -20,7 +20,6 @@
import android.app.Activity;
import android.app.Dialog;
-import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -677,16 +676,8 @@
@Override
public void onLeftSideClicked() {
- Intent settingsIntent =
- CombinedProviderInfo.createSettingsActivityIntent(
- mContext, packageName, settingsActivity, getUser());
- if (settingsIntent != null) {
- try {
- mContext.startActivity(settingsIntent);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "Failed to open settings activity", e);
- }
- }
+ CombinedProviderInfo.launchSettingsActivityIntent(
+ mContext, packageName, settingsActivity, getUser());
}
});
diff --git a/src/com/android/settings/applications/credentials/CredentialsPickerActivity.java b/src/com/android/settings/applications/credentials/CredentialsPickerActivity.java
index 495c104..479a184 100644
--- a/src/com/android/settings/applications/credentials/CredentialsPickerActivity.java
+++ b/src/com/android/settings/applications/credentials/CredentialsPickerActivity.java
@@ -16,15 +16,53 @@
package com.android.settings.applications.credentials;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.SettingsActivity;
-/** Standalone activity used to launch a {@link DefaultCombinedPicker} fragment. */
+/**
+ * Standalone activity used to launch a {@link DefaultCombinedPicker} fragment if the user is a
+ * normal user, a {@link DefaultCombinedPickerWork} fragment if the user is a work profile or {@link
+ * DefaultCombinedPickerPrivate} fragment if the user is a private profile.
+ */
public class CredentialsPickerActivity extends SettingsActivity {
+ private static final String TAG = "CredentialsPickerActivity";
+
+ /** Injects the fragment name into the intent so the correct fragment is opened. */
+ @VisibleForTesting
+ public static void injectFragmentIntoIntent(Context context, Intent intent) {
+ final int userId = UserHandle.myUserId();
+ final UserManager userManager = UserManager.get(context);
+
+ if (DefaultCombinedPickerWork.isUserHandledByFragment(userManager, userId)) {
+ Slog.d(TAG, "Creating picker fragment using work profile");
+ intent.putExtra(EXTRA_SHOW_FRAGMENT, DefaultCombinedPickerWork.class.getName());
+ } else if (DefaultCombinedPickerPrivate.isUserHandledByFragment(userManager)) {
+ Slog.d(TAG, "Creating picker fragment using private profile");
+ intent.putExtra(EXTRA_SHOW_FRAGMENT, DefaultCombinedPickerPrivate.class.getName());
+ } else {
+ Slog.d(TAG, "Creating picker fragment using normal profile");
+ intent.putExtra(EXTRA_SHOW_FRAGMENT, DefaultCombinedPicker.class.getName());
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ injectFragmentIntoIntent(this, getIntent());
+ super.onCreate(savedInstanceState);
+ }
@Override
protected boolean isValidFragment(String fragmentName) {
return super.isValidFragment(fragmentName)
- || DefaultCombinedPicker.class.getName().equals(fragmentName);
+ || DefaultCombinedPicker.class.getName().equals(fragmentName)
+ || DefaultCombinedPickerWork.class.getName().equals(fragmentName)
+ || DefaultCombinedPickerPrivate.class.getName().equals(fragmentName);
}
}
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java b/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
index 722cb1a..8d8af0e 100644
--- a/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPickerPrivate.java
@@ -17,14 +17,29 @@
package com.android.settings.applications.credentials;
import android.os.UserManager;
+import android.util.Slog;
import com.android.settings.Utils;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
public class DefaultCombinedPickerPrivate extends DefaultCombinedPicker {
+ private static final String TAG = "DefaultCombinedPickerPrivate";
+
@Override
protected int getUser() {
UserManager userManager = getContext().getSystemService(UserManager.class);
return Utils.getCurrentUserIdOfType(userManager, ProfileType.PRIVATE);
}
+
+ /** Returns whether the user is handled by this fragment. */
+ public static boolean isUserHandledByFragment(UserManager userManager) {
+ try {
+ // If there is no private profile then this will throw an exception.
+ Utils.getCurrentUserIdOfType(userManager, ProfileType.PRIVATE);
+ return true;
+ } catch (IllegalStateException e) {
+ Slog.e(TAG, "Failed to get private profile user id", e);
+ return false;
+ }
+ }
}
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPickerWork.java b/src/com/android/settings/applications/credentials/DefaultCombinedPickerWork.java
index 9808502..945d6b8 100644
--- a/src/com/android/settings/applications/credentials/DefaultCombinedPickerWork.java
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPickerWork.java
@@ -19,13 +19,16 @@
import android.os.UserHandle;
import android.os.UserManager;
-import com.android.settings.Utils;
-
public class DefaultCombinedPickerWork extends DefaultCombinedPicker {
+ private static final String TAG = "DefaultCombinedPickerWork";
@Override
protected int getUser() {
- UserHandle workProfile = Utils.getManagedProfile(UserManager.get(getContext()));
- return workProfile.getIdentifier();
+ return UserHandle.myUserId();
+ }
+
+ /** Returns whether the user is handled by this fragment. */
+ public static boolean isUserHandledByFragment(UserManager userManager, int userId) {
+ return userManager.isManagedProfile(userId);
}
}
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java b/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java
index 0fb1769..49dd7cd 100644
--- a/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceController.java
@@ -16,7 +16,6 @@
package com.android.settings.applications.credentials;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.credentials.CredentialManager;
@@ -26,11 +25,11 @@
import android.provider.Settings;
import android.service.autofill.AutofillService;
import android.service.autofill.AutofillServiceInfo;
+import android.text.TextUtils;
import android.view.autofill.AutofillManager;
-import android.util.Slog;
-import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.preference.Preference;
import com.android.internal.annotations.VisibleForTesting;
@@ -83,7 +82,7 @@
// hand side presses to align the UX.
if (PrimaryProviderPreference.shouldUseNewSettingsUi()) {
// We need to return an empty intent here since the class we inherit
- // from will throw an NPE if we return null and we don't want it to
+ // from will throw an NPE if we return null and we don't want it to
// open anything since we added the buttons.
return new Intent();
}
@@ -99,10 +98,10 @@
topProvider.getAppName(mContext),
topProvider.getSettingsSubtitle(),
topProvider.getAppIcon(mContext, getUser()),
- createSettingsActivityIntent(
- topProvider.getPackageName(), topProvider.getSettingsActivity()));
+ topProvider.getPackageName(),
+ topProvider.getSettingsActivity());
} else {
- updatePreferenceForProvider(preference, null, null, null, null);
+ updatePreferenceForProvider(preference, null, null, null, null, null);
}
}
@@ -112,7 +111,8 @@
@Nullable CharSequence appName,
@Nullable String appSubtitle,
@Nullable Drawable appIcon,
- @Nullable Intent settingsActivityIntent) {
+ @Nullable CharSequence packageName,
+ @Nullable CharSequence settingsActivity) {
if (appName == null) {
preference.setTitle(R.string.app_list_preference_none);
} else {
@@ -133,13 +133,8 @@
primaryPref.setDelegate(
new PrimaryProviderPreference.Delegate() {
public void onOpenButtonClicked() {
- if (settingsActivityIntent != null) {
- try {
- startActivity(settingsActivityIntent);
- } catch (ActivityNotFoundException e) {
- Slog.e(TAG, "Failed to open settings activity", e);
- }
- }
+ CombinedProviderInfo.launchSettingsActivityIntent(
+ mContext, packageName, settingsActivity, getUser());
}
public void onChangeButtonClicked() {
@@ -148,7 +143,7 @@
});
// Hide the open button if there is no defined settings activity.
- primaryPref.setOpenButtonVisible(settingsActivityIntent != null);
+ primaryPref.setOpenButtonVisible(!TextUtils.isEmpty(settingsActivity));
primaryPref.setButtonsVisible(appName != null);
}
}
@@ -198,13 +193,8 @@
/** Creates an intent to open the credential picker. */
private Intent createIntentToOpenPicker() {
- return new Intent(mContext, CredentialsPickerActivity.class);
- }
-
- /** Creates an intent to open the settings activity of the primary provider (if available). */
- public @Nullable Intent createSettingsActivityIntent(
- @Nullable String packageName, @Nullable String settingsActivity) {
- return CombinedProviderInfo.createSettingsActivityIntent(
- mContext, packageName, settingsActivity, getUser());
+ final Context context =
+ mContext.createContextAsUser(UserHandle.of(getUser()), /* flags= */ 0);
+ return new Intent(context, CredentialsPickerActivity.class);
}
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 0bc6176..a04d8f8 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -98,6 +98,12 @@
/** Checks whether we should show usage information by slots or not */
boolean isChartGraphSlotsEnabled(Context context);
+ /** Checks whether adaptive charging feature is supported in this device */
+ boolean isAdaptiveChargingSupported();
+
+ /** Checks whether battery manager feature is supported in this device */
+ boolean isBatteryManagerSupported();
+
/** Returns {@code true} if current defender mode is extra defend */
boolean isExtraDefend();
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index a8a2f75..75ebabb 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -149,6 +149,16 @@
}
@Override
+ public boolean isAdaptiveChargingSupported() {
+ return false;
+ }
+
+ @Override
+ public boolean isBatteryManagerSupported() {
+ return true;
+ }
+
+ @Override
public Intent getResumeChargeIntent(boolean isDockDefender) {
return null;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceController.java
new file mode 100644
index 0000000..7448003
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceController.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batterytip;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.UserManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.utils.StringUtil;
+
+/** Preference controller to control the battery manager */
+public class BatteryManagerPreferenceController extends BasePreferenceController {
+ private static final String KEY_BATTERY_MANAGER = "smart_battery_manager";
+
+ private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+ private AppOpsManager mAppOpsManager;
+ private UserManager mUserManager;
+ private boolean mEnableAppBatteryUsagePage;
+
+ public BatteryManagerPreferenceController(Context context) {
+ super(context, KEY_BATTERY_MANAGER);
+ mPowerUsageFeatureProvider = FeatureFactory.getFeatureFactory()
+ .getPowerUsageFeatureProvider();
+ mAppOpsManager = context.getSystemService(AppOpsManager.class);
+ mUserManager = context.getSystemService(UserManager.class);
+ mEnableAppBatteryUsagePage =
+ mContext.getResources().getBoolean(R.bool.config_app_battery_usage_list_enabled);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!mPowerUsageFeatureProvider.isBatteryManagerSupported()) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ if (!mContext.getResources().getBoolean(R.bool.config_battery_manager_consider_ac)) {
+ return AVAILABLE_UNSEARCHABLE;
+ }
+ return mPowerUsageFeatureProvider.isAdaptiveChargingSupported()
+ ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (!mEnableAppBatteryUsagePage) {
+ final int num = BatteryTipUtils.getRestrictedAppsList(mAppOpsManager,
+ mUserManager).size();
+ updateSummary(preference, num);
+ }
+ }
+
+ @VisibleForTesting
+ void updateSummary(Preference preference, int num) {
+ if (num > 0) {
+ preference.setSummary(StringUtil.getIcuPluralsString(mContext, num,
+ R.string.battery_manager_app_restricted));
+ } else {
+ preference.setSummary(
+ mPowerUsageFeatureProvider.isAdaptiveChargingSupported()
+ ? R.string.battery_manager_summary
+ : R.string.battery_manager_summary_unsupported);
+ }
+ }
+}
diff --git a/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java b/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java
index 9a46872..fdc4589 100644
--- a/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java
+++ b/src/com/android/settings/localepicker/TermsOfAddressFeminineController.java
@@ -35,7 +35,7 @@
@Override
protected int getMetricsActionKey() {
- return SettingsEnums.ACTION_TERMS_OF_ADDRESS_FEMININE;
+ return 0;
}
@Override
diff --git a/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java b/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java
index cb39df0..8601113 100644
--- a/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java
+++ b/src/com/android/settings/localepicker/TermsOfAddressMasculineController.java
@@ -35,7 +35,7 @@
@Override
protected int getMetricsActionKey() {
- return SettingsEnums.ACTION_TERMS_OF_ADDRESS_MASCULINE;
+ return 0;
}
@Override
diff --git a/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java b/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java
index e0693b5..e67bd4d 100644
--- a/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java
+++ b/src/com/android/settings/localepicker/TermsOfAddressNeutralController.java
@@ -35,7 +35,7 @@
@Override
protected int getMetricsActionKey() {
- return SettingsEnums.ACTION_TERMS_OF_ADDRESS_NEUTRAL;
+ return 0;
}
@Override
diff --git a/src/com/android/settings/network/SimOnboardingActivity.kt b/src/com/android/settings/network/SimOnboardingActivity.kt
new file mode 100644
index 0000000..f5dc886
--- /dev/null
+++ b/src/com/android/settings/network/SimOnboardingActivity.kt
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network
+
+import android.app.ProgressDialog
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.telephony.SubscriptionManager
+import android.util.Log
+import android.view.MotionEvent
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.SignalCellularAlt
+import androidx.compose.material3.Button
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.ModalBottomSheet
+import androidx.compose.material3.SheetState
+import androidx.compose.material3.Text
+import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import com.android.settings.R
+import com.android.settings.SidecarFragment
+import com.android.settings.network.telephony.SubscriptionActionDialogActivity
+import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
+import com.android.settings.spa.network.SimOnboardingPageProvider.getRoute
+import com.android.settingslib.spa.SpaBaseDialogActivity
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import com.android.settingslib.spa.widget.ui.SettingsTitle
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.launch
+
+class SimOnboardingActivity : SpaBaseDialogActivity() {
+ lateinit var scope: CoroutineScope
+ lateinit var showBottomSheet: MutableState<Boolean>
+ lateinit var showError: MutableState<Boolean>
+ lateinit var showDialog: MutableState<Boolean>
+
+ private var switchToEuiccSubscriptionSidecar: SwitchToEuiccSubscriptionSidecar? = null
+ private var switchToRemovableSlotSidecar: SwitchToRemovableSlotSidecar? = null
+ private var enableMultiSimSidecar: EnableMultiSimSidecar? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ if (!this.userManager.isAdminUser) {
+ Log.e(TAG, "It is not the admin user. Unable to toggle subscription.")
+ finish()
+ return
+ }
+
+ var targetSubId = intent.getIntExtra(SUB_ID,SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ initServiceData(this, targetSubId, callbackListener)
+ if (!onboardingService.isUsableTargetSubscriptionId) {
+ Log.e(TAG, "The subscription id is not usable.")
+ finish()
+ return
+ }
+
+ switchToEuiccSubscriptionSidecar = SwitchToEuiccSubscriptionSidecar.get(fragmentManager)
+ switchToRemovableSlotSidecar = SwitchToRemovableSlotSidecar.get(fragmentManager)
+ enableMultiSimSidecar = EnableMultiSimSidecar.get(fragmentManager)
+
+ setContent {
+ Content()
+ }
+ }
+
+ override fun finish() {
+ setProgressDialog(false)
+ onboardingService.clear()
+ super.finish()
+ }
+
+ var callbackListener: (Int) -> Unit = {
+ Log.d(TAG, "Receive the CALLBACK: $it")
+ when (it) {
+ CALLBACK_ERROR -> {
+ setProgressDialog(false)
+ showError.value = true
+ }
+
+ CALLBACK_ONBOARDING_COMPLETE -> {
+ showBottomSheet.value = false
+ setProgressDialog(true)
+ scope.launch {
+ // TODO: refactor the Sidecar
+ // start to activate the sim
+ startSimSwitching()
+ }
+ }
+
+ CALLBACK_SETUP_NAME -> {
+ scope.launch {
+ onboardingService.startSetupName()
+ }
+ }
+
+ CALLBACK_SETUP_PRIMARY_SIM -> {
+ scope.launch {
+ onboardingService.startSetupPrimarySim(this@SimOnboardingActivity)
+ }
+ }
+
+ CALLBACK_FINISH -> {
+ finish()
+ }
+ }
+ }
+
+ fun setProgressDialog(enable: Boolean) {
+ showDialog.value = enable
+ val progressState = if (enable) {
+ SubscriptionActionDialogActivity.PROGRESS_IS_SHOWING
+ } else {
+ SubscriptionActionDialogActivity.PROGRESS_IS_NOT_SHOWING
+ }
+ setProgressState(progressState)
+ }
+
+ @OptIn(ExperimentalMaterial3Api::class)
+ @Composable
+ override fun Content() {
+ showBottomSheet = remember { mutableStateOf(true) }
+ showError = remember { mutableStateOf(false) }
+ showDialog = remember { mutableStateOf(false) }
+ scope = rememberCoroutineScope()
+
+ registerSidecarReceiverFlow()
+
+ if(showError.value){
+ // show error
+ return
+ }
+
+ if (showBottomSheet.value) {
+ var sheetState = rememberModalBottomSheetState()
+ BottomSheetImpl(
+ sheetState = sheetState,
+ nextAction = {
+ // TODO: if the phone is SS mode and the isDsdsConditionSatisfied is true, then
+ // enable the DSDS mode.
+ // case#1: the device need the reboot after enabling DSDS. Showing the confirm
+ // dialog to user whether reboot device or not.
+ // case#2: The device don't need the reboot. Enabling DSDS and then showing
+ // the SIM onboarding UI.
+
+ // case#2
+ val route = getRoute(onboardingService.targetSubId)
+ startSpaActivity(route)
+ },
+ cancelAction = { finish() },
+ )
+ } else {
+ ProgressDialogImpl()
+ }
+ }
+
+ @Composable
+ fun ProgressDialogImpl() {
+ // TODO: 1. Create the SPA's ProgressDialog and using SPA's widget
+ val dialog: ProgressDialog = object : ProgressDialog(this) {
+ override fun onTouchEvent(event: MotionEvent): Boolean {
+ return true
+ }
+ }
+ dialog.setMessage(
+ stringResource(
+ R.string.sim_onboarding_progressbar_turning_sim_on,
+ onboardingService.targetSubInfo?.displayName ?: ""
+ )
+ )
+ dialog.setCancelable(false)
+
+ if(showDialog.value) {
+ dialog.show()
+ }
+ }
+ @Composable
+ fun registerSidecarReceiverFlow(){
+ switchToEuiccSubscriptionSidecar?.sidecarReceiverFlow()
+ ?.collectLatestWithLifecycle(LocalLifecycleOwner.current) {
+ onStateChange(it)
+ }
+ switchToRemovableSlotSidecar?.sidecarReceiverFlow()
+ ?.collectLatestWithLifecycle(LocalLifecycleOwner.current) {
+ onStateChange(it)
+ }
+ enableMultiSimSidecar?.sidecarReceiverFlow()
+ ?.collectLatestWithLifecycle(LocalLifecycleOwner.current) {
+ onStateChange(it)
+ }
+ }
+
+ fun SidecarFragment.sidecarReceiverFlow(): Flow<SidecarFragment> = callbackFlow {
+ val broadcastReceiver = SidecarFragment.Listener {
+ Log.d(TAG, "onReceive: $it")
+ trySend(it)
+ }
+ addListener(broadcastReceiver)
+
+ awaitClose { removeListener(broadcastReceiver) }
+ }.catch { e ->
+ Log.e(TAG, "Error while sidecarReceiverFlow", e)
+ }.conflate()
+
+ fun startSimSwitching(){
+ Log.d(TAG, "startSimSwitching:")
+
+ var targetSubInfo = onboardingService.targetSubInfo
+ targetSubInfo?.let {
+ var removedSubInfo = onboardingService.getRemovedSim()
+ if (targetSubInfo.isEmbedded) {
+ switchToEuiccSubscriptionSidecar!!.run(
+ targetSubInfo.subscriptionId,
+ UiccSlotUtil.INVALID_PORT_ID,
+ removedSubInfo
+ )
+ return@let
+ }
+ switchToRemovableSlotSidecar!!.run(
+ UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID,
+ removedSubInfo
+ )
+ } ?: run {
+ Log.e(TAG, "no target subInfo in onboardingService")
+ finish()
+ }
+ }
+
+ fun onStateChange(fragment: SidecarFragment?) {
+ if (fragment === switchToEuiccSubscriptionSidecar) {
+ handleSwitchToEuiccSubscriptionSidecarStateChange()
+ } else if (fragment === switchToRemovableSlotSidecar) {
+ handleSwitchToRemovableSlotSidecarStateChange()
+ } else if (fragment === enableMultiSimSidecar) {
+ handleEnableMultiSimSidecarStateChange()
+ }
+ }
+
+ fun handleSwitchToEuiccSubscriptionSidecarStateChange() {
+ when (switchToEuiccSubscriptionSidecar!!.state) {
+ SidecarFragment.State.SUCCESS -> {
+ Log.i(TAG, "Successfully enable the eSIM profile.")
+ switchToEuiccSubscriptionSidecar!!.reset()
+ callbackListener(CALLBACK_SETUP_NAME)
+ }
+
+ SidecarFragment.State.ERROR -> {
+ Log.i(TAG, "Failed to enable the eSIM profile.")
+ switchToEuiccSubscriptionSidecar!!.reset()
+ callbackListener(CALLBACK_ERROR)
+ // TODO: showErrorDialog and using privileged_action_disable_fail_title and
+ // privileged_action_disable_fail_text
+ }
+ }
+ }
+
+ fun handleSwitchToRemovableSlotSidecarStateChange() {
+ when (switchToRemovableSlotSidecar!!.state) {
+ SidecarFragment.State.SUCCESS -> {
+ Log.i(TAG, "Successfully switched to removable slot.")
+ switchToRemovableSlotSidecar!!.reset()
+ onboardingService.handleTogglePsimAction()
+ callbackListener(CALLBACK_SETUP_NAME)
+ }
+
+ SidecarFragment.State.ERROR -> {
+ Log.e(TAG, "Failed switching to removable slot.")
+ switchToRemovableSlotSidecar!!.reset()
+ callbackListener(CALLBACK_ERROR)
+ // TODO: showErrorDialog and using sim_action_enable_sim_fail_title and
+ // sim_action_enable_sim_fail_text
+ }
+ }
+ }
+
+ fun handleEnableMultiSimSidecarStateChange() {
+ when (enableMultiSimSidecar!!.state) {
+ SidecarFragment.State.SUCCESS -> {
+ enableMultiSimSidecar!!.reset()
+ Log.i(TAG, "Successfully switched to DSDS without reboot.")
+ handleEnableSubscriptionAfterEnablingDsds()
+ }
+
+ SidecarFragment.State.ERROR -> {
+ enableMultiSimSidecar!!.reset()
+ Log.i(TAG, "Failed to switch to DSDS without rebooting.")
+ callbackListener(CALLBACK_ERROR)
+ // TODO: showErrorDialog and using dsds_activation_failure_title and
+ // dsds_activation_failure_body_msg2
+ }
+ }
+ }
+
+ fun handleEnableSubscriptionAfterEnablingDsds() {
+ var targetSubInfo = onboardingService.targetSubInfo
+ if (targetSubInfo?.isEmbedded == true) {
+ Log.i(TAG,
+ "DSDS enabled, start to enable profile: " + targetSubInfo.getSubscriptionId()
+ )
+ // For eSIM operations, we simply switch to the selected eSIM profile.
+ switchToEuiccSubscriptionSidecar!!.run(
+ targetSubInfo.subscriptionId,
+ UiccSlotUtil.INVALID_PORT_ID,
+ null
+ )
+ return
+ }
+ Log.i(TAG, "DSDS enabled, start to enable pSIM profile.")
+ onboardingService.handleTogglePsimAction()
+ callbackListener(CALLBACK_FINISH)
+ }
+
+ @Composable
+ fun BottomSheetBody(nextAction: () -> Unit) {
+ Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(bottom = SettingsDimension.itemPaddingVertical)) {
+ Icon(
+ imageVector = Icons.Outlined.SignalCellularAlt,
+ contentDescription = null,
+ modifier = Modifier
+ .size(SettingsDimension.iconLarge),
+ tint = MaterialTheme.colorScheme.primary,
+ )
+ SettingsTitle(stringResource(R.string.sim_onboarding_bottomsheets_title))
+ Column(Modifier.padding(SettingsDimension.itemPadding)) {
+ Text(
+ text = stringResource(R.string.sim_onboarding_bottomsheets_msg),
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ style = MaterialTheme.typography.bodyMedium,
+ overflow = TextOverflow.Ellipsis,
+ textAlign = TextAlign.Center
+ )
+ }
+ Button(onClick = nextAction) {
+ Text(stringResource(R.string.sim_onboarding_setup))
+ }
+ }
+ }
+
+ @OptIn(ExperimentalMaterial3Api::class)
+ @Composable
+ fun BottomSheetImpl(
+ sheetState: SheetState,
+ nextAction: () -> Unit,
+ cancelAction: () -> Unit,
+ ) {
+ ModalBottomSheet(
+ onDismissRequest = cancelAction,
+ sheetState = sheetState,
+ ) {
+ BottomSheetBody(nextAction = nextAction)
+ }
+ LaunchedEffect(Unit) {
+ sheetState.show()
+ }
+ }
+
+ fun setProgressState(state: Int) {
+ val prefs = getSharedPreferences(
+ SubscriptionActionDialogActivity.SIM_ACTION_DIALOG_PREFS,
+ MODE_PRIVATE
+ )
+ prefs.edit().putInt(SubscriptionActionDialogActivity.KEY_PROGRESS_STATE, state).apply()
+ Log.i(TAG, "setProgressState:$state")
+ }
+
+ fun initServiceData(context: Context,targetSubId: Int, callback:(Int)->Unit) {
+ onboardingService.initData(targetSubId, context,callback)
+ }
+
+ companion object {
+ @JvmStatic
+ fun startSimOnboardingActivity(
+ context: Context,
+ subId: Int,
+ ) {
+ val intent = Intent(context, SimOnboardingActivity::class.java).apply {
+ putExtra(SUB_ID, subId)
+ }
+ context.startActivity(intent)
+ }
+
+ var onboardingService:SimOnboardingService = SimOnboardingService()
+ const val TAG = "SimOnboardingActivity"
+ const val SUB_ID = "sub_id"
+ const val CALLBACK_ERROR = -1
+ const val CALLBACK_ONBOARDING_COMPLETE = 1
+ const val CALLBACK_SETUP_NAME = 2
+ const val CALLBACK_SETUP_PRIMARY_SIM = 3
+ const val CALLBACK_FINISH = 4
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/network/SimOnboardingService.kt b/src/com/android/settings/network/SimOnboardingService.kt
index 1b3994e..8679385 100644
--- a/src/com/android/settings/network/SimOnboardingService.kt
+++ b/src/com/android/settings/network/SimOnboardingService.kt
@@ -23,11 +23,17 @@
import android.telephony.UiccCardInfo
import android.telephony.UiccSlotInfo
import android.util.Log
+import com.android.settings.spa.network.setAutomaticData
+import com.android.settings.spa.network.setDefaultData
+import com.android.settings.spa.network.setDefaultSms
+import com.android.settings.spa.network.setDefaultVoice
import com.android.settingslib.utils.ThreadUtils
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
private const val TAG = "SimOnboardingService"
-private const val INVALID = -1
+private const val INVALID = SubscriptionManager.INVALID_SUBSCRIPTION_ID
class SimOnboardingService {
var subscriptionManager:SubscriptionManager? = null
@@ -40,19 +46,72 @@
var slotInfoList: List<UiccSlotInfo> = listOf()
var uiccCardInfoList: List<UiccCardInfo> = listOf()
var selectedSubInfoList: MutableList<SubscriptionInfo> = mutableListOf()
- var targetPrimarySimCalls: Int = -1
- var targetPrimarySimTexts: Int = -1
- var targetPrimarySimMobileData: Int = -1
+ var targetPrimarySimCalls: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ var targetPrimarySimTexts: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ var targetPrimarySimMobileData: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ var targetPrimarySimAutoDataSwitch: Boolean = false
+ var targetNonDds: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ get() {
+ if(targetPrimarySimMobileData == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ Log.w(TAG, "No DDS")
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ }
+ return selectedSubInfoList
+ .filter { info ->
+ (info.simSlotIndex != -1) && (info.subscriptionId != targetPrimarySimMobileData)
+ }
+ .map { it.subscriptionId }
+ .firstOrNull() ?: SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ }
+ var callback: (Int) -> Unit = {}
+
var isMultipleEnabledProfilesSupported: Boolean = false
get() {
if (uiccCardInfoList.isEmpty()) {
Log.w(TAG, "UICC cards info list is empty.")
return false
}
- return uiccCardInfoList.stream()
- .anyMatch { cardInfo: UiccCardInfo -> cardInfo.isMultipleEnabledProfilesSupported }
+ return uiccCardInfoList.any { it.isMultipleEnabledProfilesSupported }
}
+ var isRemovableSimEnabled: Boolean = false
+ get() {
+ if(slotInfoList.isEmpty()) {
+ Log.w(TAG, "UICC Slot info list is empty.")
+ return false
+ }
+ return UiccSlotUtil.isRemovableSimEnabled(slotInfoList)
+ }
+
+ var doesTargetSimHaveEsimOperation = false
+ get() {
+ return targetSubInfo?.isEmbedded ?: false
+ }
+
+ var isUsableTargetSubscriptionId = false
+ get() {
+ return SubscriptionManager.isUsableSubscriptionId(targetSubId)
+ }
+ var getActiveModemCount = 0
+ get() {
+ return telephonyManager?.getActiveModemCount() ?: 0
+ }
+
var renameMutableMap : MutableMap<Int, String> = mutableMapOf()
+ var userSelectedSubInfoList : MutableList<SubscriptionInfo> = mutableListOf()
+
+ var isSimSelectionFinished = false
+ get() {
+ return getActiveModemCount != 0 && userSelectedSubInfoList.size == getActiveModemCount
+ }
+
+ var isAllOfSlotAssigned = false
+ get() {
+ if(getActiveModemCount == 0){
+ Log.e(TAG, "isAllOfSlotAssigned: getActiveModemCount is 0")
+ return true
+ }
+ return getActiveModemCount != 0 && activeSubInfoList.size == getActiveModemCount
+ }
fun isValid(): Boolean {
return targetSubId != INVALID
@@ -73,18 +132,27 @@
targetPrimarySimCalls = -1
targetPrimarySimTexts = -1
targetPrimarySimMobileData = -1
- renameMutableMap.clear()
+ clearUserRecord()
}
- fun initData(inputTargetSubId:Int,context: Context) {
+ fun clearUserRecord(){
+ renameMutableMap.clear()
+ userSelectedSubInfoList.clear()
+ }
+
+ fun initData(inputTargetSubId:Int,context: Context, callback: (Int) -> Unit) {
+ this.callback = callback
targetSubId = inputTargetSubId
subscriptionManager = context.getSystemService(SubscriptionManager::class.java)
telephonyManager = context.getSystemService(TelephonyManager::class.java)
-
+ Log.d(
+ TAG, "startInit: targetSubId:$targetSubId"
+ )
ThreadUtils.postOnBackgroundThread {
activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
availableSubInfoList = SubscriptionUtil.getAvailableSubscriptions(context)
targetSubInfo = availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
+ targetSubInfo?.let { userSelectedSubInfoList.add(it) }
Log.d(
TAG, "targetSubId: $targetSubId" + ", targetSubInfo: $targetSubInfo" +
". activeSubInfoList: $activeSubInfoList"
@@ -94,11 +162,24 @@
uiccCardInfoList = telephonyManager?.uiccCardsInfo!!
Log.d(TAG, "uiccCardInfoList: $uiccCardInfoList")
- Log.d(TAG, "isMultipleEnabledProfilesSupported: $isMultipleEnabledProfilesSupported")
+ targetPrimarySimCalls = SubscriptionManager.getDefaultVoiceSubscriptionId()
+ targetPrimarySimTexts = SubscriptionManager.getDefaultSmsSubscriptionId()
+ targetPrimarySimMobileData = SubscriptionManager.getDefaultDataSubscriptionId()
+ Log.d(
+ TAG,"doesTargetSimHaveEsimOperation: $doesTargetSimHaveEsimOperation" +
+ ", isRemovableSimEnabled: $isRemovableSimEnabled" +
+ ", isMultipleEnabledProfilesSupported: $isMultipleEnabledProfilesSupported" +
+ ", targetPrimarySimCalls: $targetPrimarySimCalls" +
+ ", targetPrimarySimTexts: $targetPrimarySimTexts" +
+ ", targetPrimarySimMobileData: $targetPrimarySimMobileData")
}
}
- fun getSelectableSubscriptionInfo(): List<SubscriptionInfo> {
+ /**
+ * Return the subscriptionInfo list which has
+ * the target subscriptionInfo + active subscriptionInfo.
+ */
+ fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> {
var list: MutableList<SubscriptionInfo> = mutableListOf()
list.addAll(activeSubInfoList)
if (!list.contains(targetSubInfo)) {
@@ -109,18 +190,102 @@
return list.toList()
}
+ /**
+ * Return the user selected SubscriptionInfo list.
+ */
+ fun getSelectedSubscriptionInfoList(): List<SubscriptionInfo> {
+ if (userSelectedSubInfoList.isEmpty()){
+ Log.d(TAG, "userSelectedSubInfoList is empty")
+ return activeSubInfoList
+ }
+ return userSelectedSubInfoList.toList()
+ }
+
fun addItemForRenaming(subInfo: SubscriptionInfo, newName: String) {
if (subInfo.displayName == newName) {
return
}
renameMutableMap[subInfo.subscriptionId] = newName
+ Log.d(TAG, "renameMutableMap add ${subInfo.subscriptionId} & $newName into: $renameMutableMap")
}
fun getSubscriptionInfoDisplayName(subInfo: SubscriptionInfo): String {
return renameMutableMap[subInfo.subscriptionId] ?: subInfo.displayName.toString()
}
- fun startActivatingSim(callback:() -> Unit){
+ fun addCurrentItemForSelectedSim(){
+ userSelectedSubInfoList.addAll(activeSubInfoList)
+ }
+
+ fun addItemForSelectedSim(selectedSubInfo: SubscriptionInfo) {
+ userSelectedSubInfoList.add(selectedSubInfo)
+ }
+
+ fun removeItemForSelectedSim(selectedSubInfo: SubscriptionInfo) {
+ if (userSelectedSubInfoList.contains(selectedSubInfo)) {
+ userSelectedSubInfoList.remove(selectedSubInfo)
+ }
+ }
+
+ /**
+ * Return the subscriptionInfo which will be removed in the slot during the sim onboarding.
+ * If return Null, then no subscriptionInfo will be removed in the slot.
+ */
+ fun getRemovedSim():SubscriptionInfo?{
+ return activeSubInfoList.find { !userSelectedSubInfoList.contains(it) }
+ }
+
+ fun handleTogglePsimAction() {
+ val canDisablePhysicalSubscription =
+ subscriptionManager?.canDisablePhysicalSubscription() == true
+ if (targetSubInfo != null && canDisablePhysicalSubscription) {
+ // TODO: to support disable case.
+ subscriptionManager?.setUiccApplicationsEnabled(
+ targetSubInfo!!.subscriptionId, /*enabled=*/true)
+ } else {
+ Log.i(TAG, "The device does not support toggling pSIM. It is enough to just "
+ + "enable the removable slot."
+ )
+ }
+ }
+
+ fun startActivatingSim(){
// TODO: start to activate sim
+ callback(SimOnboardingActivity.CALLBACK_FINISH)
+ }
+
+ suspend fun startSetupName() {
+ withContext(Dispatchers.Default) {
+ renameMutableMap.forEach {
+ subscriptionManager?.setDisplayName(
+ it.value, it.key,
+ SubscriptionManager.NAME_SOURCE_USER_INPUT
+ )
+ }
+ // next action is SETUP_PRIMARY_SIM
+ callback(SimOnboardingActivity.CALLBACK_SETUP_PRIMARY_SIM)
+ }
+ }
+
+ suspend fun startSetupPrimarySim(context: Context) {
+ withContext(Dispatchers.Default) {
+ setDefaultVoice(subscriptionManager,targetPrimarySimCalls)
+ setDefaultSms(subscriptionManager,targetPrimarySimTexts)
+ setDefaultData(
+ context,
+ subscriptionManager,
+ null,
+ targetPrimarySimMobileData
+ )
+
+
+ val telephonyManagerForNonDds: TelephonyManager? =
+ context.getSystemService(TelephonyManager::class.java)
+ ?.createForSubscriptionId(targetNonDds)
+ setAutomaticData(telephonyManagerForNonDds, targetPrimarySimAutoDataSwitch)
+
+ // no next action, send finish
+ callback(SimOnboardingActivity.CALLBACK_FINISH)
+ }
}
}
\ No newline at end of file
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index b6b433b..84e4e75 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -48,8 +48,6 @@
import com.android.settings.network.helper.SubscriptionAnnotation;
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
-import com.android.settings.spa.SpaActivity;
-import com.android.settings.spa.network.SimOnboardingPageProvider;
import java.util.ArrayList;
import java.util.Collections;
@@ -546,8 +544,7 @@
return;
}
if (enable && Flags.isDualSimOnboardingEnabled()) {
- String route = SimOnboardingPageProvider.INSTANCE.getRoute(subId);
- SpaActivity.startSpaActivity(context, route);
+ SimOnboardingActivity.startSimOnboardingActivity(context, subId);
return;
}
context.startActivity(ToggleSubscriptionDialogActivity.getIntent(context, subId, enable));
diff --git a/src/com/android/settings/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java
index 5175c23..df23f12 100644
--- a/src/com/android/settings/network/UiccSlotUtil.java
+++ b/src/com/android/settings/network/UiccSlotUtil.java
@@ -463,17 +463,27 @@
if (telMgr == null) {
return false;
}
- ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
+ List<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
+ return isRemovableSimEnabled(slotInfos);
+ }
+
+ /**
+ * Return whether the removable psim is enabled.
+ *
+ * @param slotInfos is a List of UiccSlotInfo.
+ * @return whether the removable psim is enabled.
+ */
+ public static boolean isRemovableSimEnabled(List<UiccSlotInfo> slotInfos) {
boolean isRemovableSimEnabled =
slotInfos.stream()
.anyMatch(
slot -> slot != null
&& slot.isRemovable()
&& !slot.getIsEuicc()
- && slot.getPorts().stream().anyMatch(
- port -> port.isActive())
+ && slot.getPorts().stream()
+ .anyMatch(port -> port.isActive())
&& slot.getCardStateInfo()
- == UiccSlotInfo.CARD_STATE_INFO_PRESENT);
+ == UiccSlotInfo.CARD_STATE_INFO_PRESENT);
Log.i(TAG, "isRemovableSimEnabled: " + isRemovableSimEnabled);
return isRemovableSimEnabled;
}
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index d65b2d1..4544e73 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -41,6 +41,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
+import com.android.settings.flags.Flags;
import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.network.ims.WifiCallingQueryImsState;
@@ -134,6 +135,17 @@
return;
}
+ if (Flags.isDualSimOnboardingEnabled()
+ && getProgressState() == SubscriptionActionDialogActivity.PROGRESS_IS_SHOWING
+ && (dialogType == PREFERRED_PICK
+ || dialogType == DATA_PICK
+ || dialogType == CALLS_PICK
+ || dialogType == SMS_PICK)) {
+ Log.d(TAG, "Finish the sim dialog since the sim onboarding is shown");
+ finish();
+ return;
+ }
+
final String tag = Integer.toString(dialogType);
final FragmentManager fragmentManager = getSupportFragmentManager();
SimDialogFragment fragment = (SimDialogFragment) fragmentManager.findFragmentByTag(tag);
diff --git a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
index e746d4a..b6d83f2 100644
--- a/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
+++ b/src/com/android/settings/spa/network/NetworkCellularGroupProvider.kt
@@ -67,6 +67,7 @@
import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@@ -171,6 +172,8 @@
.map { it.subscriptionId }
.firstOrNull() ?: SubscriptionManager.INVALID_SUBSCRIPTION_ID
}
+
+ Log.d(name, "defaultDataSubId: $defaultDataSubId, nonDds: $nonDds")
}
}
@@ -195,7 +198,6 @@
selectableSubscriptionInfoList
)
PrimarySimSectionImpl(
- subscriptionManager,
activeSubscriptionInfoList,
defaultVoiceSubId,
defaultSmsSubId,
@@ -257,12 +259,49 @@
@Composable
fun PrimarySimSectionImpl(
- subscriptionManager: SubscriptionManager?,
- activeSubscriptionInfoList: List<SubscriptionInfo>,
- callsSelectedId: MutableIntState,
- textsSelectedId: MutableIntState,
- mobileDataSelectedId: MutableIntState,
- nonDds: MutableIntState
+ subscriptionInfoList: List<SubscriptionInfo>,
+ callsSelectedId: MutableIntState,
+ textsSelectedId: MutableIntState,
+ mobileDataSelectedId: MutableIntState,
+ nonDds: MutableIntState,
+ subscriptionManager: SubscriptionManager? =
+ LocalContext.current.getSystemService(SubscriptionManager::class.java),
+ coroutineScope: CoroutineScope = rememberCoroutineScope(),
+ context: Context = LocalContext.current,
+ actionSetCalls: (Int) -> Unit = {
+ callsSelectedId.intValue = it
+ coroutineScope.launch {
+ setDefaultVoice(subscriptionManager, it)
+ }
+ },
+ actionSetTexts: (Int) -> Unit = {
+ textsSelectedId.intValue = it
+ coroutineScope.launch {
+ setDefaultSms(subscriptionManager, it)
+ }
+ },
+ actionSetMobileData: (Int) -> Unit = {
+ mobileDataSelectedId.intValue = it
+ coroutineScope.launch {
+ // TODO: to fix the WifiPickerTracker crash when create
+ // the wifiPickerTrackerHelper
+ setDefaultData(
+ context,
+ subscriptionManager,
+ null/*wifiPickerTrackerHelper*/,
+ it
+ )
+ }
+ },
+ actionSetAutoDataSwitch: (Boolean) -> Unit = { newState ->
+ coroutineScope.launch {
+ val telephonyManagerForNonDds: TelephonyManager? =
+ context.getSystemService(TelephonyManager::class.java)
+ ?.createForSubscriptionId(nonDds.intValue)
+ Log.d(NetworkCellularGroupProvider.name, "NonDds:${nonDds.intValue} setAutomaticData")
+ setAutomaticData(telephonyManagerForNonDds, newState)
+ }
+ },
) {
var state = rememberSaveable { mutableStateOf(false) }
var callsAndSmsList = remember {
@@ -272,11 +311,11 @@
mutableListOf(ListPreferenceOption(id = -1, text = "Loading"))
}
- if (activeSubscriptionInfoList.size >= 2) {
+ if (subscriptionInfoList.size >= 2) {
state.value = true
callsAndSmsList.clear()
dataList.clear()
- for (info in activeSubscriptionInfoList) {
+ for (info in subscriptionInfoList) {
var item = ListPreferenceOption(
id = info.subscriptionId,
text = "${info.displayName}"
@@ -291,12 +330,10 @@
} else {
// hide the primary sim
state.value = false
- Log.d("NetworkCellularGroupProvider", "Hide primary sim")
+ Log.d(NetworkCellularGroupProvider.name, "Hide primary sim")
}
if (state.value) {
- val coroutineScope = rememberCoroutineScope()
- var context = LocalContext.current
val telephonyManagerForNonDds: TelephonyManager? =
context.getSystemService(TelephonyManager::class.java)
?.createForSubscriptionId(nonDds.intValue)
@@ -305,44 +342,27 @@
}
Category(title = stringResource(id = R.string.primary_sim_title)) {
- createPrimarySimListPreference(
+ CreatePrimarySimListPreference(
stringResource(id = R.string.primary_sim_calls_title),
callsAndSmsList,
callsSelectedId,
ImageVector.vectorResource(R.drawable.ic_phone),
- ) {
- callsSelectedId.intValue = it
- coroutineScope.launch {
- setDefaultVoice(subscriptionManager, it)
- }
- }
- createPrimarySimListPreference(
+ actionSetCalls
+ )
+ CreatePrimarySimListPreference(
stringResource(id = R.string.primary_sim_texts_title),
callsAndSmsList,
textsSelectedId,
Icons.AutoMirrored.Outlined.Message,
- ) {
- textsSelectedId.intValue = it
- coroutineScope.launch {
- setDefaultSms(subscriptionManager, it)
- }
- }
- createPrimarySimListPreference(
+ actionSetTexts
+ )
+ CreatePrimarySimListPreference(
stringResource(id = R.string.mobile_data_settings_title),
dataList,
mobileDataSelectedId,
Icons.Outlined.DataUsage,
- ) {
- mobileDataSelectedId.intValue = it
- coroutineScope.launch {
- // TODO: to fix the WifiPickerTracker crash when create
- // the wifiPickerTrackerHelper
- setDefaultData(context,
- subscriptionManager,
- null/*wifiPickerTrackerHelper*/,
- it)
- }
- }
+ actionSetMobileData
+ )
}
val autoDataTitle = stringResource(id = R.string.primary_sim_automatic_data_title)
@@ -351,25 +371,18 @@
object : SwitchPreferenceModel {
override val title = autoDataTitle
override val summary = { autoDataSummary }
- override val changeable: () -> Boolean = {
- nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID
- }
override val checked = {
- coroutineScope.launch {
- withContext(Dispatchers.Default) {
- automaticDataChecked.value = telephonyManagerForNonDds != null
- && telephonyManagerForNonDds.isMobileDataPolicyEnabled(
- TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)
+ if (nonDds.intValue != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ coroutineScope.launch {
+ automaticDataChecked.value = getAutomaticData(telephonyManagerForNonDds)
}
}
automaticDataChecked.value
}
- override val onCheckedChange: ((Boolean) -> Unit)? =
- { newChecked: Boolean ->
- coroutineScope.launch {
- setAutomaticData(telephonyManagerForNonDds, newChecked)
- }
- }
+ override val onCheckedChange: ((Boolean) -> Unit)? = {
+ automaticDataChecked.value = it
+ actionSetAutoDataSwitch(it)
+ }
}
})
}
@@ -428,19 +441,19 @@
return MobileNetworkUtils.showEuiccSettings(context)
}
-private suspend fun setDefaultVoice(
+suspend fun setDefaultVoice(
subscriptionManager: SubscriptionManager?,
subId: Int): Unit = withContext(Dispatchers.Default) {
subscriptionManager?.setDefaultVoiceSubscriptionId(subId)
}
-private suspend fun setDefaultSms(
+suspend fun setDefaultSms(
subscriptionManager: SubscriptionManager?,
subId: Int): Unit = withContext(Dispatchers.Default) {
subscriptionManager?.setDefaultSmsSubId(subId)
}
-private suspend fun setDefaultData(context: Context,
+suspend fun setDefaultData(context: Context,
subscriptionManager: SubscriptionManager?,
wifiPickerTrackerHelper: WifiPickerTrackerHelper?,
subId: Int): Unit = withContext(Dispatchers.Default) {
@@ -455,11 +468,22 @@
wifiPickerTrackerHelper.setCarrierNetworkEnabled(true)
}
}
+suspend fun getAutomaticData(telephonyManagerForNonDds: TelephonyManager?): Boolean =
+ withContext(Dispatchers.Default) {
+ telephonyManagerForNonDds != null
+ && telephonyManagerForNonDds.isMobileDataPolicyEnabled(
+ TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)
+ }
-private suspend fun setAutomaticData(telephonyManager: TelephonyManager?, newState: Boolean): Unit =
- withContext(Dispatchers.Default) {
- telephonyManager?.setMobileDataPolicyEnabled(
- TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
- newState)
- //TODO: setup backup calling
- }
\ No newline at end of file
+suspend fun setAutomaticData(telephonyManager: TelephonyManager?, newState: Boolean): Unit =
+ withContext(Dispatchers.Default) {
+ Log.d(
+ "NetworkCellularGroupProvider",
+ "setAutomaticData: MOBILE_DATA_POLICY_AUTO_DATA_SWITCH as $newState"
+ )
+ telephonyManager?.setMobileDataPolicyEnabled(
+ TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
+ newState
+ )
+ //TODO: setup backup calling
+ }
\ No newline at end of file
diff --git a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
index 4cb04b6..e88c5c7 100644
--- a/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingLabelSim.kt
@@ -27,11 +27,9 @@
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settings.network.SimOnboardingService
-import com.android.settings.network.SubscriptionUtil
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.widget.dialog.AlertDialogButton
import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
@@ -74,7 +72,7 @@
SettingsBody(stringResource(R.string.sim_onboarding_label_sim_msg))
}
- for (subInfo in onboardingService.getSelectableSubscriptionInfo()) {
+ for (subInfo in onboardingService.getSelectableSubscriptionInfoList()) {
var titleSimName by remember {
mutableStateOf(
onboardingService.getSubscriptionInfoDisplayName(subInfo)
diff --git a/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt b/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt
index e46dc2e..c60ac88 100644
--- a/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingPageProvider.kt
@@ -21,6 +21,7 @@
import android.content.Context
import android.content.ContextWrapper
import android.os.Bundle
+import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
@@ -31,12 +32,12 @@
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.android.settings.R
+import com.android.settings.network.SimOnboardingActivity
import com.android.settings.network.SimOnboardingService
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.common.createSettingsPage
import com.android.settingslib.spa.framework.compose.navigator
-
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -59,7 +60,7 @@
private val owner = createSettingsPage()
@VisibleForTesting
- var onboardingService: SimOnboardingService = SimOnboardingService()
+ var onboardingService: SimOnboardingService = SimOnboardingActivity.onboardingService
fun buildInjectEntry() = SettingsEntryBuilder.createInject(owner = owner)
.setUiLayoutFn {
@@ -72,18 +73,12 @@
@Composable
override fun Page(arguments: Bundle?) {
- initServiceData(arguments!!.getInt(SUB_ID))
PageImpl(onboardingService,rememberNavController())
}
fun getRoute(
subId: Int
): String = "${name}/$subId"
-
- @Composable
- fun initServiceData(targetSubId: Int) {
- onboardingService.initData(targetSubId, LocalContext.current)
- }
}
private fun Context.getActivity(): Activity? = when (this) {
@@ -95,7 +90,10 @@
@Composable
fun PageImpl(onboardingService:SimOnboardingService,navHostController: NavHostController) {
val context = LocalContext.current
- var previousPageOfOnboarding: () -> Unit = { context.getActivity()?.finish() }
+ var finishOnboarding: () -> Unit = {
+ context.getActivity()?.finish()
+ onboardingService.callback(SimOnboardingActivity.CALLBACK_FINISH)
+ }
NavHost(
navController = navHostController,
@@ -103,31 +101,32 @@
) {
composable(route = SimOnboardingScreen.LabelSim.name) {
val nextPage =
- // Adding more conditions
- if (onboardingService.isMultipleEnabledProfilesSupported) {
+ if (onboardingService.isMultipleEnabledProfilesSupported && onboardingService.isAllOfSlotAssigned) {
SimOnboardingScreen.SelectSim.name
} else {
+ onboardingService.addCurrentItemForSelectedSim()
SimOnboardingScreen.PrimarySim.name
}
SimOnboardingLabelSimImpl(
nextAction = { navHostController.navigate(nextPage) },
- cancelAction = previousPageOfOnboarding,
+ cancelAction = finishOnboarding,
onboardingService = onboardingService
)
}
composable(route = SimOnboardingScreen.PrimarySim.name) {
SimOnboardingPrimarySimImpl(
nextAction = {
- //go back and activate sim
+ onboardingService.callback(SimOnboardingActivity.CALLBACK_ONBOARDING_COMPLETE)
+ context.getActivity()?.finish()
},
- cancelAction = previousPageOfOnboarding,
+ cancelAction = finishOnboarding,
onboardingService = onboardingService
)
}
composable(route = SimOnboardingScreen.SelectSim.name) {
SimOnboardingSelectSimImpl(
nextAction = { navHostController.navigate(SimOnboardingScreen.PrimarySim.name) },
- cancelAction = previousPageOfOnboarding,
+ cancelAction = finishOnboarding,
onboardingService = onboardingService
)
}
diff --git a/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt b/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
index 5752a4f..999abb4 100644
--- a/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingPrimarySim.kt
@@ -16,32 +16,25 @@
package com.android.settings.spa.network
+import android.telephony.SubscriptionManager
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.outlined.Message
-import androidx.compose.material.icons.outlined.DataUsage
import androidx.compose.material.icons.outlined.SignalCellularAlt
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableIntState
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.res.vectorResource
import com.android.settings.R
import com.android.settings.network.SimOnboardingService
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.widget.preference.ListPreference
import com.android.settingslib.spa.widget.preference.ListPreferenceModel
import com.android.settingslib.spa.widget.preference.ListPreferenceOption
-import com.android.settingslib.spa.widget.preference.SwitchPreference
-import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
import com.android.settingslib.spa.widget.scaffold.SuwScaffold
import com.android.settingslib.spa.widget.ui.SettingsBody
@@ -68,84 +61,54 @@
cancelAction
),
) {
- primarySimBody(onboardingService)
- }
-}
-
-@Composable
-private fun primarySimBody(onboardingService: SimOnboardingService) {
- //TODO: Load the status from the frameworks
- var callsSelectedId = rememberSaveable { mutableIntStateOf(1) }
- var textsSelectedId = rememberSaveable { mutableIntStateOf(1) }
- var mobileDataSelectedId = rememberSaveable { mutableIntStateOf(1) }
- var automaticDataChecked by rememberSaveable { mutableStateOf(true) }
-
- Column(Modifier.padding(SettingsDimension.itemPadding)) {
- SettingsBody(stringResource(id = R.string.sim_onboarding_primary_sim_msg))
- }
- var selectableSubscriptionInfo = onboardingService.getSelectableSubscriptionInfo()
- var list = listOf(ListPreferenceOption(id = -1, text = "Loading"))
- if (selectableSubscriptionInfo.size >= 2) {
- list = listOf(
- ListPreferenceOption(
- id = selectableSubscriptionInfo[0].subscriptionId,
- text = "${selectableSubscriptionInfo[0].displayName}"
- ),
- ListPreferenceOption(
- id = selectableSubscriptionInfo[1].subscriptionId,
- text = "${selectableSubscriptionInfo[1].displayName}"
- ),
- ListPreferenceOption(
- id = -1,
- text = stringResource(id = R.string.sim_calls_ask_first_prefs_title)
- ),
- )
- } else {
- // set all of primary sim items' enable as false and showing that sim.
- }
- createPrimarySimListPreference(
- stringResource(id = R.string.primary_sim_calls_title),
- list,
- callsSelectedId,
- ImageVector.vectorResource(R.drawable.ic_phone),
- onIdSelected = { callsSelectedId.intValue = it }
- )
- createPrimarySimListPreference(
- stringResource(id = R.string.primary_sim_texts_title),
- list,
- textsSelectedId,
- Icons.AutoMirrored.Outlined.Message,
- onIdSelected = { textsSelectedId.intValue = it }
- )
-
- createPrimarySimListPreference(
- stringResource(id = R.string.mobile_data_settings_title),
- list,
- mobileDataSelectedId,
- Icons.Outlined.DataUsage,
- onIdSelected = { mobileDataSelectedId.intValue = it }
- )
-
- val autoDataTitle = stringResource(id = R.string.primary_sim_automatic_data_title)
- val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
- SwitchPreference(remember {
- object : SwitchPreferenceModel {
- override val title = autoDataTitle
- override val summary = { autoDataSummary }
- override val checked = { automaticDataChecked }
- override val onCheckedChange =
- { newChecked: Boolean -> automaticDataChecked = newChecked }
+ val callsSelectedId = rememberSaveable {
+ mutableIntStateOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
}
- })
+ val textsSelectedId = rememberSaveable {
+ mutableIntStateOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ }
+ val mobileDataSelectedId = rememberSaveable {
+ mutableIntStateOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ }
+ val nonDdsRemember = rememberSaveable {
+ mutableIntStateOf(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ }
+
+ Column(Modifier.padding(SettingsDimension.itemPadding)) {
+ SettingsBody(stringResource(id = R.string.sim_onboarding_primary_sim_msg))
+ }
+
+ var selectedSubscriptionInfoList = onboardingService.getSelectedSubscriptionInfoList()
+ callsSelectedId.intValue = onboardingService.targetPrimarySimCalls
+ textsSelectedId.intValue = onboardingService.targetPrimarySimTexts
+ mobileDataSelectedId.intValue = onboardingService.targetPrimarySimMobileData
+ PrimarySimSectionImpl(
+ subscriptionInfoList = selectedSubscriptionInfoList,
+ callsSelectedId = callsSelectedId,
+ textsSelectedId = textsSelectedId,
+ mobileDataSelectedId = mobileDataSelectedId,
+ nonDds = nonDdsRemember,
+ actionSetCalls = {
+ callsSelectedId.intValue = it
+ onboardingService.targetPrimarySimCalls = it},
+ actionSetTexts = {
+ textsSelectedId.intValue = it
+ onboardingService.targetPrimarySimTexts = it},
+ actionSetMobileData = {
+ mobileDataSelectedId.intValue = it
+ onboardingService.targetPrimarySimMobileData = it},
+ actionSetAutoDataSwitch = {
+ onboardingService.targetPrimarySimAutoDataSwitch = it},
+ )
+ }
}
@Composable
-fun createPrimarySimListPreference(
+fun CreatePrimarySimListPreference(
title: String,
list: List<ListPreferenceOption>,
selectedId: MutableIntState,
icon: ImageVector,
- enable: Boolean = true,
onIdSelected: (id: Int) -> Unit
) = ListPreference(remember {
object : ListPreferenceModel {
@@ -156,7 +119,5 @@
override val icon = @Composable {
SettingsIcon(icon)
}
- override val enabled: () -> Boolean
- get() = { enable }
}
})
\ No newline at end of file
diff --git a/src/com/android/settings/spa/network/SimOnboardingSelectSim.kt b/src/com/android/settings/spa/network/SimOnboardingSelectSim.kt
index 1955d13..5e71b12 100644
--- a/src/com/android/settings/spa/network/SimOnboardingSelectSim.kt
+++ b/src/com/android/settings/spa/network/SimOnboardingSelectSim.kt
@@ -16,24 +16,23 @@
package com.android.settings.spa.network
+import android.util.Log
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.SignalCellularAlt
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settings.network.SimOnboardingService
+import com.android.settings.sim.SimDialogActivity
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.widget.preference.CheckboxPreference
import com.android.settingslib.spa.widget.preference.CheckboxPreferenceModel
-
import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
import com.android.settingslib.spa.widget.scaffold.SuwScaffold
import com.android.settingslib.spa.widget.ui.SettingsBody
@@ -68,22 +67,38 @@
Column(Modifier.padding(SettingsDimension.itemPadding)) {
SettingsBody(stringResource(id = R.string.sim_onboarding_select_sim_msg))
}
- for (subInfo in onboardingService.getSelectableSubscriptionInfo()) {
+ var isFinished = rememberSaveable { mutableStateOf(false) }
+ isFinished.value = onboardingService.isSimSelectionFinished
+ for (subInfo in onboardingService.getSelectableSubscriptionInfoList()) {
var title = onboardingService.getSubscriptionInfoDisplayName(subInfo)
var summaryNumber =
subInfo.number // TODO using the SubscriptionUtil.getFormattedPhoneNumber
- var changeable = subInfo.isActive
- var checked by rememberSaveable { mutableStateOf(!subInfo.isActive) }
+ var checked = rememberSaveable {
+ mutableStateOf(
+ onboardingService.getSelectedSubscriptionInfoList().contains(subInfo)
+ )
+ }
CheckboxPreference(remember {
object : CheckboxPreferenceModel {
override val title = title
override val summary: () -> String
get() = { summaryNumber }
- override val checked = { checked }
- override val changeable = { changeable }
- override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
+ override val checked = { checked.value }
+ override val onCheckedChange = { newChecked: Boolean ->
+ checked.value = newChecked
+ if (newChecked) {
+ onboardingService.addItemForSelectedSim(subInfo)
+ } else {
+ onboardingService.removeItemForSelectedSim(subInfo)
+ }
+ isFinished.value = onboardingService.isSimSelectionFinished
+ }
+ override val changeable = {
+ subInfo.isActive
+ && (!isFinished.value || (isFinished.value && checked.value))
+ }
}
})
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index 0131330..db4c359 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -134,6 +134,11 @@
}
@Test
+ public void testIsAdaptiveChargingSupported_returnFalse() {
+ assertThat(mPowerFeatureProvider.isAdaptiveChargingSupported()).isFalse();
+ }
+
+ @Test
public void testGetResumeChargeIntentWithoutDockDefender_returnNull() {
assertThat(mPowerFeatureProvider.getResumeChargeIntent(false)).isNull();
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceControllerTest.java
new file mode 100644
index 0000000..f7469c7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryManagerPreferenceControllerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.fuelgauge.batterytip;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = SettingsShadowResources.class)
+public class BatteryManagerPreferenceControllerTest {
+ private static final int ON = 1;
+ private static final int OFF = 0;
+
+ @Mock
+ private AppOpsManager mAppOpsManager;
+
+ private Context mContext;
+ private Preference mPreference;
+ private FakeFeatureFactory mFeatureFactory;
+ private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+ private BatteryManagerPreferenceController mController;
+
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mPreference = new Preference(mContext);
+ mController = new BatteryManagerPreferenceController(mContext);
+ mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
+ }
+
+ @Test
+ public void updateState_smartBatteryWithRestrictApps_showSummary() {
+ mController.updateSummary(mPreference, 2);
+
+ assertThat(mPreference.getSummary()).isEqualTo("2 apps restricted");
+ }
+
+ @Test
+ public void updateState_smartBatteryWithoutRestriction_showSummary() {
+ when(mPowerUsageFeatureProvider.isSmartBatterySupported()).thenReturn(true);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, ON);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary()).isEqualTo("Detecting when apps drain battery");
+ }
+
+ @Test
+ public void getAvailabilityStatus_supportBatteryManager_showPrefPage() {
+ SettingsShadowResources.overrideResource(
+ R.bool.config_battery_manager_consider_ac, true);
+ when(mPowerUsageFeatureProvider.isBatteryManagerSupported()).thenReturn(true);
+ when(mPowerUsageFeatureProvider.isAdaptiveChargingSupported()).thenReturn(true);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BatteryManagerPreferenceController.AVAILABLE_UNSEARCHABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_notSupportBatteryManager_notShowPrefPage() {
+ when(mPowerUsageFeatureProvider.isBatteryManagerSupported()).thenReturn(false);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BatteryManagerPreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_supportBatteryManagerWithoutAC_notShowPrefPage() {
+ SettingsShadowResources.overrideResource(
+ R.bool.config_battery_manager_consider_ac, true);
+ when(mPowerUsageFeatureProvider.isBatteryManagerSupported()).thenReturn(true);
+ when(mPowerUsageFeatureProvider.isAdaptiveChargingSupported()).thenReturn(false);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BatteryManagerPreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_ignoreBatteryManagerWithoutAC_showPrefPage() {
+ SettingsShadowResources.overrideResource(
+ R.bool.config_battery_manager_consider_ac, false);
+ when(mPowerUsageFeatureProvider.isBatteryManagerSupported()).thenReturn(true);
+ when(mPowerUsageFeatureProvider.isAdaptiveChargingSupported()).thenReturn(false);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BatteryManagerPreferenceController.AVAILABLE_UNSEARCHABLE);
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
index dace5e9..8e12b20 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
@@ -108,7 +108,7 @@
on { targetSubInfo }.doReturn(SUB_INFO_1)
on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
- on { getSelectableSubscriptionInfo() }.doReturn(
+ on { getSelectableSubscriptionInfoList() }.doReturn(
listOf(
SUB_INFO_1,
SUB_INFO_2,
@@ -139,7 +139,7 @@
on { targetSubInfo }.doReturn(SUB_INFO_1)
on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
- on { getSelectableSubscriptionInfo() }.doReturn(
+ on { getSelectableSubscriptionInfoList() }.doReturn(
listOf(
SUB_INFO_1,
SUB_INFO_2,
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
index 35f1968..82dba76 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingPageProviderTest.kt
@@ -91,6 +91,7 @@
fun simOnboardingPage_nextAction_fromLabelSimToSelectSim() {
mockSimOnboardingService.stub {
on { isMultipleEnabledProfilesSupported }.thenReturn(true)
+ on { isAllOfSlotAssigned }.thenReturn(true)
}
composeTestRule.setContent {
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
index 5d7465f..45667ef 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
@@ -108,7 +108,7 @@
on { targetSubInfo }.doReturn(SUB_INFO_1)
on { availableSubInfoList }.doReturn(listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3))
on { activeSubInfoList }.doReturn(listOf(SUB_INFO_2, SUB_INFO_3))
- on { getSelectableSubscriptionInfo() }.doReturn(
+ on { getSelectableSubscriptionInfoList() }.doReturn(
listOf(
SUB_INFO_1,
SUB_INFO_2,
diff --git a/tests/unit/src/com/android/settings/applications/credentials/CredentialsPickerActivityTest.java b/tests/unit/src/com/android/settings/applications/credentials/CredentialsPickerActivityTest.java
new file mode 100644
index 0000000..044c23d
--- /dev/null
+++ b/tests/unit/src/com/android/settings/applications/credentials/CredentialsPickerActivityTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.credentials;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.google.common.collect.Lists;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class CredentialsPickerActivityTest {
+
+ @Mock private UserManager mUserManager;
+
+ private Context mMockContext;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mMockContext = spy(ApplicationProvider.getApplicationContext());
+ when(mMockContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
+ }
+
+ @Test
+ public void testInjectFragmentIntoIntent_normalProfile() {
+ Intent intent = new Intent();
+ CredentialsPickerActivity.injectFragmentIntoIntent(mMockContext, intent);
+ assertThat(intent.getStringExtra(CredentialsPickerActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(DefaultCombinedPicker.class.getName());
+ }
+
+ @Test
+ public void testInjectFragmentIntoIntent_workProfile() {
+ Intent intent = new Intent();
+
+ // Simulate managed / work profile.
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
+ assertThat(DefaultCombinedPickerWork.isUserHandledByFragment(mUserManager, 10)).isTrue();
+
+ CredentialsPickerActivity.injectFragmentIntoIntent(mMockContext, intent);
+ assertThat(intent.getStringExtra(CredentialsPickerActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(DefaultCombinedPickerWork.class.getName());
+ }
+
+ @Test
+ public void testInjectFragmentIntoIntent_privateProfile() {
+ Intent intent = new Intent();
+
+ // Simulate private profile.
+ UserHandle privateUser = new UserHandle(100);
+ when(mUserManager.getUserInfo(100))
+ .thenReturn(new UserInfo(100, "", "", 0, UserManager.USER_TYPE_PROFILE_PRIVATE));
+ when(mUserManager.getUserProfiles()).thenReturn(Lists.newArrayList(privateUser));
+ assertThat(DefaultCombinedPickerPrivate.isUserHandledByFragment(mUserManager)).isTrue();
+
+ CredentialsPickerActivity.injectFragmentIntoIntent(mMockContext, intent);
+ assertThat(intent.getStringExtra(CredentialsPickerActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(DefaultCombinedPickerPrivate.class.getName());
+ }
+}
diff --git a/tests/unit/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceControllerTest.java
index 301fcfa..d02240e 100644
--- a/tests/unit/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/credentials/DefaultCombinedPreferenceControllerTest.java
@@ -87,16 +87,14 @@
@Test
public void ensureSettingsActivityIntentCreatedSuccessfully() {
- DefaultCombinedPreferenceController dcpc =
- new DefaultCombinedPreferenceController(mContext);
-
// Ensure that the settings activity is only created if we haved the right combination
// of package and class name.
- assertThat(dcpc.createSettingsActivityIntent(null, null)).isNull();
- assertThat(dcpc.createSettingsActivityIntent("", null)).isNull();
- assertThat(dcpc.createSettingsActivityIntent("", "")).isNull();
- assertThat(dcpc.createSettingsActivityIntent("com.test", "")).isNull();
- assertThat(dcpc.createSettingsActivityIntent("com.test", "ClassName")).isNotNull();
+ assertThat(CombinedProviderInfo.createSettingsActivityIntent(null, null)).isNull();
+ assertThat(CombinedProviderInfo.createSettingsActivityIntent("", null)).isNull();
+ assertThat(CombinedProviderInfo.createSettingsActivityIntent("", "")).isNull();
+ assertThat(CombinedProviderInfo.createSettingsActivityIntent("com.test", "")).isNull();
+ assertThat(CombinedProviderInfo.createSettingsActivityIntent("com.test", "ClassName"))
+ .isNotNull();
}
@Test
@@ -112,13 +110,13 @@
// Update the preference to use the provider and make sure the view
// was updated.
- dcpc.updatePreferenceForProvider(ppp, "App Name", "Subtitle", appIcon, null);
+ dcpc.updatePreferenceForProvider(ppp, "App Name", "Subtitle", appIcon, null, null);
assertThat(ppp.getTitle().toString()).isEqualTo("App Name");
assertThat(ppp.getSummary().toString()).isEqualTo("Subtitle");
assertThat(ppp.getIcon()).isEqualTo(appIcon);
// Set the preference back to none and make sure the view was updated.
- dcpc.updatePreferenceForProvider(ppp, null, null, null, null);
+ dcpc.updatePreferenceForProvider(ppp, null, null, null, null, null);
assertThat(ppp.getTitle().toString()).isEqualTo("None");
assertThat(ppp.getSummary()).isNull();
assertThat(ppp.getIcon()).isNull();
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt b/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt
new file mode 100644
index 0000000..794cfec
--- /dev/null
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/feature/SfpsEnrollmentFeatureImplTest.kt
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint.feature
+
+import android.animation.Animator
+import android.content.Context
+import android.hardware.fingerprint.FingerprintManager
+import android.view.View
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_CENTER
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_FINGERTIP
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_LEFT_EDGE
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_NO_ANIMATION
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_RIGHT_EDGE
+import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.STAGE_UNKNOWN
+import com.google.common.truth.Truth.assertThat
+import kotlin.math.roundToInt
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidJUnit4::class)
+class SfpsEnrollmentFeatureImplTest {
+ @get:Rule
+ val mockito: MockitoRule = MockitoJUnit.rule()
+
+ @Spy
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ private val settingsPackageName = "com.android.settings"
+
+ private lateinit var settingsContext: Context
+
+ @Mock
+ private lateinit var mockFingerprintManager: FingerprintManager
+
+ private val mSfpsEnrollmentFeatureImpl: SfpsEnrollmentFeatureImpl = SfpsEnrollmentFeatureImpl()
+
+ @Before
+ fun setUp() {
+ assertThat(mSfpsEnrollmentFeatureImpl).isInstanceOf(SfpsEnrollmentFeatureImpl::class.java)
+ whenever(context.getSystemService(FingerprintManager::class.java))
+ .thenReturn(mockFingerprintManager)
+ doReturn(0f).`when`(mockFingerprintManager).getEnrollStageThreshold(0)
+ doReturn(0.36f).`when`(mockFingerprintManager).getEnrollStageThreshold(1)
+ doReturn(0.52f).`when`(mockFingerprintManager).getEnrollStageThreshold(2)
+ doReturn(0.76f).`when`(mockFingerprintManager).getEnrollStageThreshold(3)
+ doReturn(1f).`when`(mockFingerprintManager).getEnrollStageThreshold(4)
+ settingsContext = context.createPackageContext(settingsPackageName, 0)
+ }
+
+ @Test
+ fun testGetEnrollStageThreshold() {
+ assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 0)).isEqualTo(0f)
+ assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 1)).isEqualTo(0.36f)
+ assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 2)).isEqualTo(0.52f)
+ assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 3)).isEqualTo(0.76f)
+ assertThat(mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, 4)).isEqualTo(1f)
+ }
+
+ @Test
+ fun testGetHelpAnimator() {
+ val mockView: View = mock(View::class.java)
+ val animator: Animator = mSfpsEnrollmentFeatureImpl.getHelpAnimator(mockView)
+ assertThat(animator.duration).isEqualTo(550)
+ }
+
+ @Test
+ fun testGetCurrentSfpsEnrollStage() {
+ assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(0, null))
+ .isEqualTo(STAGE_UNKNOWN)
+ val mapper = { i: Int ->
+ (25 * mSfpsEnrollmentFeatureImpl.getEnrollStageThreshold(context, i)).roundToInt()
+ }
+ assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(-1, mapper))
+ .isEqualTo(SFPS_STAGE_NO_ANIMATION)
+ assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(0, mapper))
+ .isEqualTo(SFPS_STAGE_CENTER)
+ assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(9, mapper))
+ .isEqualTo(SFPS_STAGE_FINGERTIP)
+ assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(13, mapper))
+ .isEqualTo(SFPS_STAGE_LEFT_EDGE)
+ assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(19, mapper))
+ .isEqualTo(SFPS_STAGE_RIGHT_EDGE)
+ assertThat(mSfpsEnrollmentFeatureImpl.getCurrentSfpsEnrollStage(25, mapper))
+ .isEqualTo(SFPS_STAGE_RIGHT_EDGE)
+ }
+
+ @Test
+ fun testGetFeaturedStageHeaderResource() {
+ val type = "string"
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_NO_ANIMATION)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "security_settings_fingerprint_enroll_repeat_title",
+ type,
+ settingsPackageName)
+ )
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_CENTER)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "security_settings_sfps_enroll_finger_center_title",
+ type,
+ settingsPackageName)
+ )
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_FINGERTIP)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "security_settings_sfps_enroll_fingertip_title",
+ type,
+ settingsPackageName)
+ )
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_LEFT_EDGE)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "security_settings_sfps_enroll_left_edge_title",
+ type,
+ settingsPackageName)
+ )
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getFeaturedStageHeaderResource(SFPS_STAGE_RIGHT_EDGE)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "security_settings_sfps_enroll_right_edge_title",
+ type,
+ settingsPackageName)
+ )
+ }
+
+ @Test
+ fun testGetSfpsEnrollLottiePerStage() {
+ val type = "raw"
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_NO_ANIMATION)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "sfps_lottie_no_animation",
+ type,
+ settingsPackageName)
+ )
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_CENTER)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "sfps_lottie_pad_center",
+ type,
+ settingsPackageName)
+ )
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_FINGERTIP)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "sfps_lottie_tip",
+ type,
+ settingsPackageName)
+ )
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_LEFT_EDGE)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "sfps_lottie_left_edge",
+ type,
+ settingsPackageName)
+ )
+ assertThat(
+ mSfpsEnrollmentFeatureImpl.getSfpsEnrollLottiePerStage(SFPS_STAGE_RIGHT_EDGE)
+ ).isEqualTo(
+ settingsContext.resources.getIdentifier(
+ "sfps_lottie_right_edge",
+ type,
+ settingsPackageName)
+ )
+ }
+}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java
index c04e5f9..d1e3078 100644
--- a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressFeminineControllerTest.java
@@ -97,7 +97,6 @@
selectedPreference.performClick();
- assertThat(selectedPreference.getKey()).isEqualTo(KEY_FEMININE);
assertThat(selectedPreference.isSelected()).isTrue();
assertThat(pref.isSelected()).isFalse();
}
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java
index c2298be..5bf3073 100644
--- a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressMasculineControllerTest.java
@@ -97,7 +97,6 @@
selectedPreference.performClick();
- assertThat(selectedPreference.getKey()).isEqualTo(KEY_MASCULINE);
assertThat(selectedPreference.isSelected()).isTrue();
assertThat(pref.isSelected()).isFalse();
}
diff --git a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java
index fb207fc..e83f3cd 100644
--- a/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java
+++ b/tests/unit/src/com/android/settings/localepicker/TermsOfAddressNeutralControllerTest.java
@@ -97,7 +97,6 @@
selectedPreference.performClick();
- assertThat(selectedPreference.getKey()).isEqualTo(KEY_NEUTRAL);
assertThat(selectedPreference.isSelected()).isTrue();
assertThat(pref.isSelected()).isFalse();
}
diff --git a/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java b/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
index 4aae76c..daa2afb 100644
--- a/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
@@ -34,7 +34,7 @@
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
+import androidx.preference.SwitchPreferenceCompat;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -275,7 +275,7 @@
PreferenceGroup group = (PreferenceGroup) mGroupList.getPreference(0);
assertEquals("group", group.getKey());
assertEquals(3, group.getPreferenceCount());
- SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
+ SwitchPreferenceCompat groupBlockPref = (SwitchPreferenceCompat) group.getPreference(0);
assertNull(groupBlockPref.getKey());
assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
assertTrue(groupBlockPref.isChecked());
@@ -297,7 +297,7 @@
PreferenceGroup group = (PreferenceGroup) mGroupList.getPreference(0);
assertEquals("group", group.getKey());
assertEquals(1, group.getPreferenceCount());
- SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
+ SwitchPreferenceCompat groupBlockPref = (SwitchPreferenceCompat) group.getPreference(0);
assertNull(groupBlockPref.getKey());
assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
assertFalse(groupBlockPref.isChecked());
@@ -311,7 +311,7 @@
PreferenceGroup group = (PreferenceGroup) mGroupList.getPreference(0);
assertEquals("group", group.getKey());
assertEquals(3, group.getPreferenceCount());
- SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
+ SwitchPreferenceCompat groupBlockPref = (SwitchPreferenceCompat) group.getPreference(0);
assertNull(groupBlockPref.getKey());
assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
assertTrue(groupBlockPref.isChecked());