Merge "Add sliceUri in broadcast intent"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index caca444..3933b9c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -717,8 +717,7 @@
android:name="Settings$ZenModeSettingsActivity"
android:label="@string/zen_mode_settings_title"
android:icon="@drawable/ic_notifications"
- android:exported="true"
- android:parentActivityName="Settings">
+ android:exported="true">
<intent-filter android:priority="1">
<action android:name="android.settings.ZEN_MODE_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
@@ -875,8 +874,7 @@
android:name="Settings$NightDisplaySettingsActivity"
android:label="@string/night_display_title"
android:enabled="@*android:bool/config_nightDisplayAvailable"
- android:icon="@drawable/ic_settings_night_display"
- android:parentActivityName="Settings">
+ android:icon="@drawable/ic_settings_night_display">
<intent-filter android:priority="32">
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.SHORTCUT" />
@@ -1626,7 +1624,7 @@
android:icon="@drawable/ic_settings_security">
<intent-filter android:priority="1">
<action android:name="android.intent.action.MAIN" />
- <category android:name="com.android.settings.suggested.category.LOCK_SCREEN" />
+ <category android:name="com.android.settings.suggested.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.title"
android:resource="@string/suggested_lock_settings_title" />
@@ -2821,10 +2819,8 @@
android:name=".Settings$AppAndNotificationDashboardActivity"
android:label="@string/app_and_notification_dashboard_title"
android:icon="@drawable/ic_homepage_apps"
- android:parentActivityName="Settings">
- <intent-filter>
- <action android:name="com.android.settings.action.SETTINGS"/>
- </intent-filter>
+ android:parentActivityName="Settings"
+ android:exported="true">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.AppAndNotificationDashboardFragment"/>
</activity>
diff --git a/res/layout/slice_preference_layout.xml b/res/layout/slice_preference_layout.xml
new file mode 100644
index 0000000..4cea9c0
--- /dev/null
+++ b/res/layout/slice_preference_layout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ <androidx.slice.widget.SliceView
+ android:id="@+id/slice_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+</FrameLayout>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 86763b7..383506d 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -52,6 +52,8 @@
<attr name="apnPreferenceStyle" format="reference" />
+ <attr name="slicePreferenceStyle" format="reference" />
+
<attr name="footerPreferenceStyle" format="reference" />
<declare-styleable name="FixedLineSummaryPreference">
diff --git a/res/values/config.xml b/res/values/config.xml
index edd948f7..7108cbd 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -165,4 +165,7 @@
<!-- Email address for the homepage contextual cards feedback -->
<string name="config_contextual_card_feedback_email" translatable="false"></string>
+
+ <!-- Uri that represents extra bluetooth settings -->
+ <string name="config_bluetooth_device_settings_uri" translatable="false">content://com.google.android.gms.nearby.fastpair/settings_slice?addr=<xliff:g id="mac_address">%1$s</xliff:g></string>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1aaa374..d07cc53 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6963,6 +6963,8 @@
<string name="keywords_sim_status">network, mobile network state, service state, signal strength, mobile network type, roaming, iccid</string>
<string name="keywords_model_and_hardware">serial number, hardware version</string>
<string name="keywords_android_version">android security patch level, baseband version, kernel version</string>
+ <!--Search keywords for financial apps sms access settings -->
+ <string name="keywords_financial_apps_sms_access">financial app, sms, permission</string>
<!-- Search keyword for Device Theme Settings [CHAR LIMIT=NONE] -->
<string name="keywords_systemui_theme">dark theme</string>
@@ -8853,6 +8855,10 @@
<!-- Summary of number of apps currently can write system settings [CHAR LIMIT=60] -->
<string name="write_settings_summary"><xliff:g id="count" example="10">%1$d</xliff:g> of <xliff:g id="count" example="10">%2$d</xliff:g> apps allowed to modify system settings</string>
+ <!-- Settings title in main settings screen for financial apps sms access [CHAR LIMIT=60] -->
+ <string name="financial_apps_sms_access_title">Financial Apps Sms Access</string>
+ <!-- Preference key for financial apps sms access screen -->
+ <string name="financial_sms_root_screen_key" translatable="false">financial_sms_root_screen_key</string>
<!-- Label for showing apps that can install other apps [CHAR LIMIT=45] -->
<string name="filter_install_sources_apps">Can install other apps</string>
<!-- Label for showing apps that can write system settings [CHAR LIMIT=45] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 48cd876..15ec46d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -489,4 +489,8 @@
<item name="android:textAllCaps">false</item>
</style>
+ <style name="Widget.SliceView.Settings">
+ <item name="titleSize">@*android:dimen/text_size_subhead_material</item>
+ </style>
+
</resources>
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index 0f7ecab..f25289d 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -21,6 +21,7 @@
<style name="PreferenceTheme" parent="@style/PreferenceThemeOverlay.SettingsBase">
<item name="apnPreferenceStyle">@style/ApnPreference</item>
+ <item name="slicePreferenceStyle">@style/SlicePreference</item>
<item name="seekBarPreferenceStyle">@style/SettingsSeekBarPreference</item>
<item name="twoStateButtonPreferenceStyle">@style/TwoStateButtonPreference</item>
</style>
@@ -34,6 +35,10 @@
<item name="android:layout">@layout/apn_preference_layout</item>
</style>
+ <style name="SlicePreference" parent="@style/Preference.Material">
+ <item name="android:layout">@layout/slice_preference_layout</item>
+ </style>
+
<style name="SettingsSeekBarPreference" parent="@style/Preference.Material">
<item name="android:layout">@layout/preference_widget_seekbar_settings</item>
</style>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 390be584..f22d111 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -32,9 +32,13 @@
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
<item name="face_layout_theme">@style/FaceLayoutTheme</item>
<item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_holo_dark</item>
+
+ <!-- For wifi icon -->
<item name="wifi_signal">@drawable/wifi_signal</item>
<item name="wifi_signal_color">?android:attr/colorAccent</item>
<item name="wifi_friction">@drawable/wifi_friction</item>
+ <item name="frictionIconColor">?android:colorControlNormal</item>
+
<item name="side_margin">@dimen/settings_side_margin</item>
<item name="suwListItemIconColor">?android:attr/colorAccent</item>
@@ -58,6 +62,9 @@
<!-- TODO(118444000): Remove colorPrimary and colorPrimaryVariant -->
<item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
<item name="colorPrimaryVariant">@android:color/white</item>
+
+ <!-- For slice view in settings -->
+ <item name="sliceViewStyle">@style/Widget.SliceView.Settings</item>
</style>
<!-- Variant of the settings theme with no action bar. -->
@@ -71,9 +78,6 @@
<item name="android:actionBarStyle">@style/Widget.ActionBar.SubSettings</item>
<item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.Settings</item>
-
- <!-- Friction icon color for wifi preferences -->
- <item name="frictionIconColor">?android:colorControlNormal</item>
</style>
<style name="Theme.SubSettings" parent="Theme.SubSettings.Base"/>
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index 40ce93d..90895f2 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -26,7 +26,14 @@
settings:allowDividerBelow="true"/>
<com.android.settingslib.widget.ActionButtonsPreference
- android:key="action_buttons" />
+ android:key="action_buttons"
+ settings:allowDividerBelow="true"/>
+
+ <com.android.settings.slices.SlicePreference
+ android:key="bt_device_slice"
+ settings:controller="com.android.settings.slices.SlicePreferenceController"
+ settings:allowDividerBelow="true"
+ settings:allowDividerAbove="true"/>
<PreferenceCategory
android:key="bluetooth_profiles"/>
diff --git a/res/xml/financial_app_sms_access.xml b/res/xml/financial_app_sms_access.xml
new file mode 100644
index 0000000..6f7ba50
--- /dev/null
+++ b/res/xml/financial_app_sms_access.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:key="@string/financial_sms_root_screen_key"
+ android:title="@string/financial_apps_sms_access_title"
+ settings:controller="com.android.settings.applications.specialaccess.financialapps.FinancialAppsController" />
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 57e673f..cb76693 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -130,4 +130,9 @@
android:value="com.android.settings.Settings$ChangeWifiStateActivity" />
</Preference>
+ <Preference
+ android:key="financial_apps_sms_access"
+ android:title="@string/financial_apps_sms_access_title"
+ android:fragment="com.android.settings.applications.specialaccess.financialapps.FinancialAppsSmsAccess"
+ settings:keywords="@string/keywords_financial_apps_sms_access" />
</PreferenceScreen>
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 6557aee..fdd7f2e 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -32,7 +32,6 @@
import com.android.settings.display.ThemePreferenceController;
import com.android.settings.display.TimeoutPreferenceController;
import com.android.settings.display.VrDisplayPreferenceController;
-import com.android.settings.display.WallpaperPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
diff --git a/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsController.java b/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsController.java
new file mode 100644
index 0000000..492e4fd
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsController.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.applications.specialaccess.financialapps;
+
+import static android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS;
+import static android.Manifest.permission.READ_SMS;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.SwitchPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FinancialAppsController extends BasePreferenceController
+ implements ApplicationsState.Callbacks {
+ private final static String TAG = FinancialAppsController.class.getSimpleName();
+
+ @VisibleForTesting
+ PreferenceScreen mRoot;
+
+ public FinancialAppsController(Context context, String key) {
+ super(context, key);
+ }
+
+ @AvailabilityStatus
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mRoot = screen;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ updateList();
+ }
+
+ private void updateList() {
+ mRoot.removeAll();
+
+ final PackageManager packageManager = mContext.getPackageManager();
+ final AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+
+ final List<PackageInfo> installedPackages =
+ packageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
+ final int numPackages = installedPackages.size();
+ for (int i = 0; i < numPackages; i++) {
+ final PackageInfo installedPackage = installedPackages.get(i);
+
+ if (installedPackage.requestedPermissions == null) {
+ continue;
+ }
+ final int targetSdk = installedPackage.applicationInfo.targetSdkVersion;
+ final String pkgName = installedPackage.packageName;
+
+ if ((targetSdk >= Build.VERSION_CODES.Q
+ && ArrayUtils.contains(installedPackage.requestedPermissions,
+ SMS_FINANCIAL_TRANSACTIONS))
+ || (targetSdk < Build.VERSION_CODES.Q
+ && ArrayUtils.contains(installedPackage.requestedPermissions,
+ READ_SMS))) {
+ final SwitchPreference pref = new SwitchPreference(mRoot.getContext());
+ pref.setTitle(installedPackage.applicationInfo.loadLabel(packageManager));
+ pref.setKey(pkgName);
+
+ pref.setChecked(
+ appOpsManager.checkOp(
+ targetSdk >= Build.VERSION_CODES.Q
+ ? AppOpsManager.OP_SMS_FINANCIAL_TRANSACTIONS
+ : AppOpsManager.OP_READ_SMS,
+ installedPackage.applicationInfo.uid,
+ pkgName) == AppOpsManager.MODE_ALLOWED);
+
+ pref.setOnPreferenceChangeListener((preference, newValue) -> {
+ final int uid;
+ try {
+ uid = packageManager.getPackageInfo(preference.getKey(), 0)
+ .applicationInfo.uid;
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "onPreferenceChange: Failed to get uid for "
+ + preference.getKey());
+ return false;
+ }
+
+ appOpsManager.setMode(
+ targetSdk >= Build.VERSION_CODES.Q
+ ? AppOpsManager.OP_SMS_FINANCIAL_TRANSACTIONS
+ : AppOpsManager.OP_READ_SMS,
+ uid,
+ pkgName,
+ (Boolean) newValue ? AppOpsManager.MODE_ALLOWED
+ : AppOpsManager.MODE_IGNORED);
+ return true;
+ });
+ mRoot.addPreference(pref);
+ }
+ }
+ }
+
+ @Override
+ public void onRunningStateChanged(boolean running) {}
+
+ @Override
+ public void onPackageListChanged() {
+ updateList();
+ }
+
+ @Override
+ public void onRebuildComplete(ArrayList<AppEntry> apps) {}
+
+ @Override
+ public void onPackageIconChanged() {}
+
+ @Override
+ public void onPackageSizeChanged(String packageName) {}
+
+ @Override
+ public void onAllSizesComputed() {}
+
+ @Override
+ public void onLauncherInfoChanged() {}
+
+ @Override
+ public void onLoadEntriesCompleted() {}
+}
diff --git a/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsSmsAccess.java b/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsSmsAccess.java
new file mode 100644
index 0000000..92f4e28
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsSmsAccess.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.financialapps;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SearchIndexable
+public class FinancialAppsSmsAccess extends DashboardFragment {
+ private final static String TAG = FinancialAppsSmsAccess.class.getSimpleName();
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.financial_app_sms_access;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.SETTINGS_FINANCIAL_APPS_SMS_ACCESS;
+ }
+
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ final ArrayList<SearchIndexableResource> result = new ArrayList<>();
+
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.financial_app_sms_access;
+ result.add(sir);
+ return result;
+ }
+ };
+}
diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java
index 0aa8936..2597b29 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollBase.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java
@@ -67,8 +67,11 @@
*/
public static final int RESULT_TIMEOUT = RESULT_FIRST_USER + 2;
- public static final int CONFIRM_REQUEST = 1;
- public static final int ENROLLING = 2;
+ public static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
+ public static final int BIOMETRIC_FIND_SENSOR_REQUEST = 2;
+ public static final int LEARN_MORE_REQUEST = 3;
+ public static final int CONFIRM_REQUEST = 4;
+ public static final int ENROLLING = 5;
protected boolean mLaunchedConfirmLock;
protected byte[] mToken;
@@ -105,10 +108,6 @@
initViews();
}
- protected boolean shouldLaunchConfirmLock() {
- return mToken == null && !mLaunchedConfirmLock;
- }
-
protected void initViews() {
getWindow().setStatusBarColor(Color.TRANSPARENT);
Button nextButton = getNextButton();
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 2424eb1..8a2a8ec 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -37,10 +37,6 @@
public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
implements LinkSpan.OnClickListener {
- public static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
- public static final int BIOMETRIC_FIND_SENSOR_REQUEST = 2;
- public static final int LEARN_MORE_REQUEST = 3;
-
private UserManager mUserManager;
private boolean mHasPassword;
private boolean mBiometricUnlockDisabledByAdmin;
@@ -110,6 +106,11 @@
protected abstract Intent getEnrollingIntent();
/**
+ * @return the title to be shown on the ConfirmLock screen.
+ */
+ protected abstract int getConfirmLockTitleResId();
+
+ /**
* @param span
*/
public abstract void onClick(LinkSpan span);
@@ -133,6 +134,13 @@
mUserManager = UserManager.get(this);
updatePasswordQuality();
+
+ if (!mHasPassword) {
+ // No password registered, launch into enrollment wizard.
+ launchChooseLock();
+ } else {
+ launchConfirmLock(getConfirmLockTitleResId(), getChallenge());
+ }
}
@Override
@@ -157,13 +165,8 @@
@Override
protected void onNextButtonClick() {
- if (!mHasPassword) {
- // No biometrics registered, launch into enrollment wizard.
- launchChooseLock();
- } else {
- // Lock thingy is already set up, launch directly into find sensor step from wizard.
- launchFindSensor(null);
- }
+ // Lock thingy is already set up, launch directly to the next page
+ launchNextEnrollingActivity(mToken);
}
private void launchChooseLock() {
@@ -181,7 +184,7 @@
startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
}
- private void launchFindSensor(byte[] token) {
+ private void launchNextEnrollingActivity(byte[] token) {
Intent intent = getEnrollingIntent();
if (token != null) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
@@ -199,9 +202,9 @@
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
final boolean isResultFinished = resultCode == RESULT_FINISHED;
+ final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
if (isResultFinished || resultCode == RESULT_SKIP) {
- final int result = isResultFinished ? RESULT_OK : RESULT_SKIP;
setResult(result, data);
finish();
return;
@@ -209,10 +212,21 @@
} else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
if (isResultFinished) {
updatePasswordQuality();
- byte[] token = data.getByteArrayExtra(
+ mToken = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
- launchFindSensor(token);
+ overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
return;
+ } else {
+ setResult(result, data);
+ finish();
+ }
+ } else if (requestCode == CONFIRM_REQUEST) {
+ if (resultCode == RESULT_OK && data != null) {
+ mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
+ overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
+ } else {
+ setResult(result, data);
+ finish();
}
} else if (requestCode == LEARN_MORE_REQUEST) {
overridePendingTransition(R.anim.suw_slide_back_in, R.anim.suw_slide_back_out);
diff --git a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
index f101038..033fb4b 100644
--- a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
@@ -48,13 +48,6 @@
*/
protected abstract boolean shouldStartAutomatically();
- /**
- * @return true if enrollment should finish when onStop is called.
- */
- protected boolean shouldFinishOnStop() {
- return true;
- }
-
@Override
protected void onStart() {
super.onStart();
@@ -70,7 +63,7 @@
mSidecar.setListener(null);
}
- if (shouldFinishOnStop() && !isChangingConfigurations()) {
+ if (!isChangingConfigurations()) {
if (mSidecar != null) {
mSidecar.cancelEnrollment();
getSupportFragmentManager()
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
index 727d74a..bb46b18 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
@@ -44,7 +44,6 @@
private TextView mErrorText;
private Interpolator mLinearOutSlowInInterpolator;
- private boolean mShouldFinishOnStop = true;
private FaceEnrollPreviewFragment mPreviewFragment;
private FaceFeatureProvider.Listener mListener = new FaceFeatureProvider.Listener() {
@@ -92,13 +91,7 @@
Button skipButton = findViewById(R.id.skip_button);
skipButton.setOnClickListener(this);
- if (shouldLaunchConfirmLock()) {
- launchConfirmLock(R.string.security_settings_face_preference_title,
- Utils.getFaceManagerOrNull(this).generateChallenge());
- mShouldFinishOnStop = false;
- } else {
- startEnrollment();
- }
+ startEnrollment();
}
@Override
@@ -130,11 +123,6 @@
}
@Override
- protected boolean shouldFinishOnStop() {
- return mShouldFinishOnStop;
- }
-
- @Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.FACE_ENROLL_ENROLLING;
}
@@ -178,23 +166,6 @@
}
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == CONFIRM_REQUEST) {
- if (resultCode == RESULT_OK && data != null) {
- mShouldFinishOnStop = true;
- mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
- overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
- getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
- startEnrollment();
- } else {
- finish();
- }
- } else {
- super.onActivityResult(requestCode, resultCode, data);
- }
- }
-
private void showErrorDialog(CharSequence msg, int msgId) {
BiometricErrorDialog dialog = FaceErrorDialog.newInstance(msg, msgId);
dialog.show(getSupportFragmentManager(), FaceErrorDialog.class.getName());
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index c4a9c4f..b720ff4 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -102,6 +102,7 @@
@Override
protected long getChallenge() {
+ mFaceManager = Utils.getFaceManagerOrNull(this);
if (mFaceManager == null) {
return 0;
}
@@ -119,6 +120,11 @@
}
@Override
+ protected int getConfirmLockTitleResId() {
+ return R.string.security_settings_face_preference_title;
+ }
+
+ @Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.FACE_ENROLL_INTRO;
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
index 4b4f65a..0772c66 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
@@ -51,12 +51,9 @@
setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
- if (shouldLaunchConfirmLock()) {
- launchConfirmLock(R.string.security_settings_fingerprint_preference_title,
- Utils.getFingerprintManagerOrNull(this).preEnroll());
- } else if (mToken != null) {
- startLookingForFingerprint(); // already confirmed, so start looking for fingerprint
- }
+
+ startLookingForFingerprint(); // already confirmed, so start looking for fingerprint
+
View animationView = findViewById(R.id.fingerprint_sensor_location_animation);
if (animationView instanceof FingerprintFindSensorAnimation) {
mAnimation = (FingerprintFindSensorAnimation) animationView;
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 8821ce5..61c67a5 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -106,6 +106,7 @@
@Override
protected long getChallenge() {
+ mFingerprintManager = Utils.getFingerprintManagerOrNull(this);
if (mFingerprintManager == null) {
return 0;
}
@@ -123,6 +124,11 @@
}
@Override
+ protected int getConfirmLockTitleResId() {
+ return R.string.security_settings_fingerprint_preference_title;
+ }
+
+ @Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.FINGERPRINT_ENROLL_INTRO;
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index df32111..6ec419b 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -21,12 +21,16 @@
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Bundle;
+import android.util.FeatureFlagUtils;
import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settings.core.FeatureFlags;
import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.slices.SlicePreferenceController;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -98,6 +102,13 @@
mManager = getLocalBluetoothManager(context);
mCachedDevice = getCachedDevice(mDeviceAddress);
super.onAttach(context);
+
+ if (FeatureFlagUtils.isEnabled(context, FeatureFlags.SLICE_INJECTION)) {
+ final BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(context)
+ .getBluetoothFeatureProvider(context);
+ use(SlicePreferenceController.class).setSliceUri(
+ featureProvider.getBluetoothDeviceSettingsUri(mDeviceAddress));
+ }
}
@Override
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
new file mode 100644
index 0000000..2bca038
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProvider.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.net.Uri;
+
+/**
+ * Provider for bluetooth related feature
+ */
+public interface BluetoothFeatureProvider {
+
+ /**
+ * Get the {@link Uri} that represents extra settings for a specific bluetooth device
+ * @param macAddress Bluetooth mac address
+ * @return {@link Uri} for extra settings
+ */
+ Uri getBluetoothDeviceSettingsUri(String macAddress);
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
new file mode 100644
index 0000000..dcdc2fd7
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothFeatureProviderImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.settings.R;
+
+/**
+ * Impl of {@link BluetoothFeatureProvider}
+ */
+public class BluetoothFeatureProviderImpl implements BluetoothFeatureProvider {
+
+ private Context mContext;
+
+ public BluetoothFeatureProviderImpl(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public Uri getBluetoothDeviceSettingsUri(String macAddress) {
+ final String uriString = mContext.getString(R.string.config_bluetooth_device_settings_uri,
+ macAddress);
+ return Uri.parse(uriString);
+ }
+}
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 56e9ee5..1916110 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -295,7 +295,13 @@
if (!controller.isAvailable()) {
continue;
}
+
final String key = controller.getPreferenceKey();
+ if (TextUtils.isEmpty(key)) {
+ Log.d(TAG, String.format("Preference key is %s in Controller %s",
+ key, controller.getClass().getSimpleName()));
+ continue;
+ }
final Preference preference = screen.findPreference(key);
if (preference == null) {
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 0320bf6..cf7df8d 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -24,6 +24,7 @@
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.biometrics.face.FaceFeatureProvider;
+import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
@@ -114,6 +115,8 @@
public abstract FaceFeatureProvider getFaceFeatureProvider();
+ public abstract BluetoothFeatureProvider getBluetoothFeatureProvider(Context context);
+
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 0232964..e10aa41 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -30,6 +30,8 @@
import com.android.settings.applications.ApplicationFeatureProviderImpl;
import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.biometrics.face.FaceFeatureProviderImpl;
+import com.android.settings.bluetooth.BluetoothFeatureProvider;
+import com.android.settings.bluetooth.BluetoothFeatureProviderImpl;
import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl;
import com.android.settings.core.instrumentation.SettingsMetricsFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
@@ -81,6 +83,7 @@
private PanelFeatureProvider mPanelFeatureProvider;
private ContextualCardFeatureProvider mContextualCardFeatureProvider;
private FaceFeatureProvider mFaceFeatureProvider;
+ private BluetoothFeatureProvider mBluetoothFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -243,4 +246,13 @@
}
return mFaceFeatureProvider;
}
+
+ @Override
+ public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
+ if (mBluetoothFeatureProvider == null) {
+ mBluetoothFeatureProvider = new BluetoothFeatureProviderImpl(
+ context.getApplicationContext());
+ }
+ return mBluetoothFeatureProvider;
+ }
}
diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java
index b96c57df..8454cc5 100644
--- a/src/com/android/settings/password/SetupChooseLockPassword.java
+++ b/src/com/android/settings/password/SetupChooseLockPassword.java
@@ -135,8 +135,9 @@
@Override
protected void updateUi() {
super.updateUi();
- mSkipButton.setVisibility(mForFingerprint ? View.GONE : View.VISIBLE);
+ // Show the skip button during SUW but not during Settings > Biometric Enrollment
+ mSkipButton.setVisibility(View.VISIBLE);
if (mOptionsButton != null) {
mOptionsButton.setVisibility(
mUiStage == Stage.Introduction ? View.VISIBLE : View.GONE);
diff --git a/src/com/android/settings/password/SetupChooseLockPattern.java b/src/com/android/settings/password/SetupChooseLockPattern.java
index 696380c..b24936b 100644
--- a/src/com/android/settings/password/SetupChooseLockPattern.java
+++ b/src/com/android/settings/password/SetupChooseLockPattern.java
@@ -70,17 +70,15 @@
ChooseLockTypeDialogFragment.newInstance(mUserId)
.show(getChildFragmentManager(), null));
}
- // enable skip button only during setup wizard and not with fingerprint flow.
- if (!mForFingerprint) {
- Button skipButton = view.findViewById(R.id.skip_button);
- skipButton.setVisibility(View.VISIBLE);
- skipButton.setOnClickListener(v -> {
- SetupSkipDialog dialog = SetupSkipDialog.newInstance(
- getActivity().getIntent()
- .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false));
- dialog.show(getFragmentManager());
+ // Show the skip button during SUW but not during Settings > Biometric Enrollment
+ Button skipButton = view.findViewById(R.id.skip_button);
+ skipButton.setVisibility(View.VISIBLE);
+ skipButton.setOnClickListener(v -> {
+ SetupSkipDialog dialog = SetupSkipDialog.newInstance(
+ getActivity().getIntent()
+ .getBooleanExtra(SetupSkipDialog.EXTRA_FRP_SUPPORTED, false));
+ dialog.show(getFragmentManager());
});
- }
return view;
}
diff --git a/src/com/android/settings/slices/SlicePreference.java b/src/com/android/settings/slices/SlicePreference.java
new file mode 100644
index 0000000..98719f7
--- /dev/null
+++ b/src/com/android/settings/slices/SlicePreference.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.slices;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceView;
+
+import com.android.settings.R;
+import com.android.settingslib.widget.LayoutPreference;
+
+/**
+ * Preference for {@link SliceView}
+ */
+public class SlicePreference extends LayoutPreference {
+ private SliceView mSliceView;
+
+ public SlicePreference(Context context, AttributeSet attrs) {
+ super(context, attrs, R.attr.slicePreferenceStyle);
+ mSliceView = findViewById(R.id.slice_view);
+ }
+
+ public SlicePreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, R.attr.slicePreferenceStyle);
+ mSliceView = findViewById(R.id.slice_view);
+ }
+
+ public void onSliceUpdated(Slice slice) {
+ mSliceView.onChanged(slice);
+ notifyChanged();
+ }
+}
diff --git a/src/com/android/settings/slices/SlicePreferenceController.java b/src/com/android/settings/slices/SlicePreferenceController.java
new file mode 100644
index 0000000..8c751c8
--- /dev/null
+++ b/src/com/android/settings/slices/SlicePreferenceController.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.slices;
+
+import android.content.Context;
+import android.net.Uri;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.Observer;
+import androidx.preference.PreferenceScreen;
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceLiveData;
+import androidx.slice.widget.SliceView;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+/**
+ * Default {@link BasePreferenceController} for {@link SliceView}. It will take {@link Uri} for
+ * Slice and display what's inside this {@link Uri}
+ */
+public class SlicePreferenceController extends BasePreferenceController implements
+ LifecycleObserver, OnStart, OnStop, Observer<Slice> {
+ @VisibleForTesting
+ LiveData<Slice> mLiveData;
+ private SlicePreference mSlicePreference;
+ private Uri mUri;
+
+ public SlicePreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+
+ mSlicePreference = (SlicePreference) screen.findPreference(
+ getPreferenceKey());
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mUri != null ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+
+ public void setSliceUri(Uri uri) {
+ mUri = uri;
+ mLiveData = SliceLiveData.fromUri(mContext, mUri);
+
+ //TODO(b/120803703): figure out why we need to remove observer first
+ mLiveData.removeObserver(this);
+ }
+
+ @Override
+ public void onStart() {
+ if (mLiveData != null) {
+ mLiveData.observeForever(this);
+ }
+ }
+
+ @Override
+ public void onStop() {
+ if (mLiveData != null) {
+ mLiveData.removeObserver(this);
+ }
+ }
+
+ @Override
+ public void onChanged(Slice slice) {
+ mSlicePreference.onSliceUpdated(slice);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsControllerTest.java
new file mode 100644
index 0000000..39a05cb
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/financialapps/FinancialAppsControllerTest.java
@@ -0,0 +1,125 @@
+package com.android.settings.applications.specialaccess.financialapps;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import static android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS;
+import static android.Manifest.permission.READ_SMS;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+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.shadow.api.Shadow;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
+public class FinancialAppsControllerTest {
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private AppOpsManager mAppOpsManager;
+ @Mock
+ private PreferenceScreen mRoot;
+ @Mock
+ private Preference mPreference;
+
+ private Context mContext;
+ private PackageInfo mPackageInfoNoPermissionRequested;
+ private PackageInfo mPackageInfoPermissionRequestedQPlus;
+ private PackageInfo mPackageInfoPermissionRequestedPreQ;
+ private FinancialAppsController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+
+ initializePackageInfos();
+
+ mController = new FinancialAppsController(mContext, "key");
+ mController.displayPreference(mRoot);
+ }
+
+ private void initializePackageInfos() {
+ mPackageInfoNoPermissionRequested = new PackageInfo();
+ mPackageInfoNoPermissionRequested.applicationInfo = new ApplicationInfo();
+
+ mPackageInfoPermissionRequestedQPlus = new PackageInfo();
+ mPackageInfoPermissionRequestedQPlus.applicationInfo = new ApplicationInfo();
+ // TODO(b/121161546): update after robolectric test support Q
+ //mPackageInfoPermissionRequestedQPlus.applicationInfo.targetSdkVersion =
+ // Build.VERSION_CODES.Q;
+ mPackageInfoPermissionRequestedQPlus.applicationInfo.uid = 2001;
+ mPackageInfoPermissionRequestedQPlus.applicationInfo.nonLocalizedLabel = "QPLUS Package";
+ mPackageInfoPermissionRequestedQPlus.packageName = "QPLUS";
+ mPackageInfoPermissionRequestedQPlus.requestedPermissions =
+ new String[] {SMS_FINANCIAL_TRANSACTIONS};
+
+ mPackageInfoPermissionRequestedPreQ = new PackageInfo();
+ mPackageInfoPermissionRequestedPreQ.applicationInfo = new ApplicationInfo();
+ mPackageInfoPermissionRequestedPreQ.applicationInfo.targetSdkVersion = Build.VERSION_CODES.M;
+ mPackageInfoPermissionRequestedPreQ.applicationInfo.uid = 2002;
+ mPackageInfoPermissionRequestedPreQ.applicationInfo.nonLocalizedLabel = "PREQ Package";
+ mPackageInfoPermissionRequestedPreQ.packageName = "PREQ";
+ mPackageInfoPermissionRequestedPreQ.requestedPermissions = new String[] {READ_SMS};
+ }
+
+ @Test
+ public void isAvailable_true() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void noPreferenceAddedWhenNoPackageRequestPermission() {
+ when(mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS))
+ .thenReturn(new ArrayList<PackageInfo>(
+ Arrays.asList(mPackageInfoNoPermissionRequested)));
+ mController.updateState(null);
+ assertThat(mController.mRoot.getPreferenceCount()).isEqualTo(0);
+ }
+
+ //TODO(b/121161546): Add these tests after robolectric test support Q
+ /*
+ @Test
+ public void preferenceAddedWhenPreQPackageRequestPermission() {
+ when(mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS))
+ .thenReturn(new ArrayList<PackageInfo>(
+ Arrays.asList(mPackageInfoPermissionRequestedPreQ)));
+ mController.updateState(null);
+ assertThat(mController.mRoot.getPreferenceCount()).isEqualTo(1);
+ SwitchPreference pref = (SwitchPreference) mController.mRoot.getPreference(0);
+ assertThat(pref).isNotNull();
+ }
+
+ @Test
+ public void preferenceAddedWhenQPlusPackageRequestPermission() {
+ when(mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS))
+ .thenReturn(new ArrayList<PackageInfo>(
+ Arrays.asList(mPackageInfoPermissionRequestedQPlus)));
+ mController.updateState(null);
+ assertThat(mController.mRoot.getPreferenceCount()).isEqualTo(1);
+ SwitchPreference pref = (SwitchPreference) mController.mRoot.getPreference(0);
+ assertThat(pref).isNotNull();
+ }*/
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
new file mode 100644
index 0000000..887f58c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothFeatureProviderImplTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothFeatureProviderImplTest {
+ private static final String PARAMETER_KEY = "addr";
+ private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
+ private BluetoothFeatureProvider mBluetoothFeatureProvider;
+
+ @Before
+ public void setUp() {
+ mBluetoothFeatureProvider = new BluetoothFeatureProviderImpl(
+ RuntimeEnvironment.application);
+ }
+
+ @Test
+ public void getBluetoothDeviceSettingsUri_containCorrectMacAddress() {
+ final Uri uri = mBluetoothFeatureProvider.getBluetoothDeviceSettingsUri(MAC_ADDRESS);
+ assertThat(uri.getQueryParameterNames()).containsExactly(PARAMETER_KEY);
+ assertThat(uri.getQueryParameter(PARAMETER_KEY)).isEqualTo(MAC_ADDRESS);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
index c11d7eb..649a1ba 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
@@ -164,23 +164,6 @@
assertThat(findFragment(mActivity).mChosenPattern).isNull();
}
- @Test
- public void skipButton_shouldNotBeVisible_duringFingerprintFlow() {
- final Intent intent =
- SetupChooseLockPattern.modifyIntentForSetup(
- application,
- new IntentBuilder(application)
- .setUserId(UserHandle.myUserId())
- .setForFingerprint(true)
- .build());
-
- mActivity = ActivityController.of(new SetupChooseLockPattern(), intent).setup().get();
- Button skipButton = mActivity.findViewById(R.id.skip_button);
-
- assertThat(skipButton).isNotNull();
- assertThat(skipButton.getVisibility()).isEqualTo(View.GONE);
- }
-
private ChooseLockPatternFragment findFragment(FragmentActivity activity) {
return (ChooseLockPatternFragment)
activity.getSupportFragmentManager().findFragmentById(R.id.main_content);
diff --git a/tests/robotests/src/com/android/settings/slices/SlicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/slices/SlicePreferenceControllerTest.java
new file mode 100644
index 0000000..364fb60
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/slices/SlicePreferenceControllerTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.net.Uri;
+
+import androidx.lifecycle.LiveData;
+import androidx.slice.Slice;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class SlicePreferenceControllerTest {
+ private static final String KEY = "slice_preference_key";
+
+ @Mock
+ private LiveData<Slice> mLiveData;
+ private Context mContext;
+ private SlicePreferenceController mController;
+ private Uri mUri;
+
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ mController = new SlicePreferenceController(mContext, KEY);
+ mController.mLiveData = mLiveData;
+ mUri = Uri.EMPTY;
+ }
+
+ @Test
+ public void isAvailable_uriNull_returnFalse() {
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_uriNotNull_returnTrue() {
+ mController.setSliceUri(mUri);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void onStart_registerObserver() {
+ mController.onStart();
+ verify(mLiveData).observeForever(mController);
+ }
+
+ @Test
+ public void onStop_unregisterObserver() {
+ mController.onStop();
+ verify(mLiveData).removeObserver(mController);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index 1d8e2cb..bf86898 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -24,6 +24,7 @@
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.biometrics.face.FaceFeatureProvider;
+import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
@@ -66,6 +67,7 @@
public final AccountFeatureProvider mAccountFeatureProvider;
public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
public final FaceFeatureProvider mFaceFeatureProvider;
+ public final BluetoothFeatureProvider mBluetoothFeatureProvider;
public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
@@ -111,6 +113,7 @@
mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
panelFeatureProvider = mock(PanelFeatureProvider.class);
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
+ mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class);
}
@Override
@@ -206,4 +209,9 @@
public FaceFeatureProvider getFaceFeatureProvider() {
return mFaceFeatureProvider;
}
+
+ @Override
+ public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
+ return mBluetoothFeatureProvider;
+ }
}