Merge "Add keywords for wifi slice"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b708471..92a1066 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2622,6 +2622,8 @@
android:name=".wifi.NetworkRequestDialogActivity"
android:theme="@style/Transparent"
android:excludeFromRecents="true"
+ android:launchMode="singleTop"
+ android:taskAffinity=".wifi.NetworkRequestDialogActivity"
android:exported="true"
android:permission="android.permission.NETWORK_SETTINGS">
<intent-filter>
@@ -2971,6 +2973,17 @@
</intent-filter>
</service>
+ <service
+ android:name=".development.qstile.DevelopmentTiles$SensorsOff"
+ android:label="@string/sensors_off_quick_settings_title"
+ android:icon="@drawable/tile_icon_sensors_off"
+ android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
+ android:enabled="false">
+ <intent-filter>
+ <action android:name="android.service.quicksettings.action.QS_TILE" />
+ </intent-filter>
+ </service>
+
<activity
android:name=".HelpTrampoline"
android:exported="true"
diff --git a/res/drawable/tile_icon_sensors_off.xml b/res/drawable/tile_icon_sensors_off.xml
new file mode 100644
index 0000000..890fa83
--- /dev/null
+++ b/res/drawable/tile_icon_sensors_off.xml
@@ -0,0 +1,39 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M21.966,2 L2,22"
+ android:strokeLineCap="round"
+ android:strokeColor="#000000"
+ android:fillColor="#00000000"
+ android:strokeWidth="1.6521436"
+ android:strokeLineJoin="miter"
+ android:strokeAlpha="1"/>
+ <path
+ android:pathData="M0.752,12L4.496,12l2.496,-6.25 2.496,12.5 2.496,-15 2.496,12.5 2.496,-7.5 1.248,3.75h4.992"
+ android:strokeLineCap="round"
+ android:strokeColor="#000000"
+ android:fillColor="#00000000"
+ android:strokeWidth="1.25090861"
+ android:strokeLineJoin="round"
+ android:strokeAlpha="1"/>
+</vector>
+
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
index 3a0e659..c408a97 100644
--- a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -60,10 +60,10 @@
android:id="@+id/error_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
android:textAlignment="center"
- android:layout_marginTop="8dp"
- android:visibility="invisible"
- android:textColor="?android:attr/colorError"/>
+ android:textColor="?android:attr/colorError"
+ android:visibility="invisible"/>
</LinearLayout>
diff --git a/res/layout/manage_applications_apps.xml b/res/layout/manage_applications_apps.xml
index 87db820..9c90f02 100644
--- a/res/layout/manage_applications_apps.xml
+++ b/res/layout/manage_applications_apps.xml
@@ -26,41 +26,34 @@
android:layout_height="match_parent"
settings:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior">
- <LinearLayout
+ <FrameLayout
android:id="@+id/list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"
android:visibility="gone">
- <FrameLayout
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/apps_list"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:clipToPadding="false"
+ settings:fastScrollEnabled="true"
+ settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
+ settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
+ settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
+ settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable"/>
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/apps_list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipToPadding="false"
- settings:fastScrollEnabled="true"
- settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
- settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
- settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
- settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable"/>
+ <TextView
+ android:id="@android:id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:text="@string/no_applications"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:visibility="invisible"/>
- <TextView
- android:id="@android:id/empty"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:layout_gravity="center"
- android:text="@string/no_applications"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:visibility="invisible"/>
-
- </FrameLayout>
-
- </LinearLayout>
+ </FrameLayout>
<include layout="@layout/loading_container"/>
diff --git a/res/layout/settings_homepage.xml b/res/layout/settings_homepage.xml
index e04b372..6e2b302 100644
--- a/res/layout/settings_homepage.xml
+++ b/res/layout/settings_homepage.xml
@@ -21,7 +21,7 @@
android:layout_height="wrap_content"
android:orientation="vertical">
- <androidx.recyclerview.widget.RecyclerView
+ <com.android.settings.homepage.contextualcards.FocusRecyclerView
android:id="@+id/card_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/res/layout/wifi_dpp_qrcode_generator_fragment.xml b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
index 2617aea..31bf7cc 100644
--- a/res/layout/wifi_dpp_qrcode_generator_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
@@ -40,6 +40,14 @@
android:layout_height="@dimen/qrcode_size"
android:src="@android:color/transparent"/>
+ <TextView
+ android:id="@+id/password"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:textAlignment="center"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary"/>
</LinearLayout>
</ScrollView>
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 4fa8e8b..9bd742a 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -60,10 +60,10 @@
android:id="@+id/error_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
android:textAlignment="center"
- android:layout_marginTop="8dp"
- android:visibility="invisible"
- android:textColor="?android:attr/colorError"/>
+ android:textColor="?android:attr/colorError"
+ android:visibility="invisible"/>
</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 088be5c..0986634 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2129,7 +2129,9 @@
<!-- Title for the fragment to share Wi-Fi [CHAR LIMIT=50] -->
<string name="wifi_dpp_share_wifi">Share Wi\u2011Fi</string>
<!-- Hint for the user to use another device to scan QR code on screen to join Wi-Fi [CHAR LIMIT=NONE] -->
- <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code with another device to join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
+ <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code to connect to \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d and share the password</string>
+ <!-- Hint for the user to use another device to scan QR code on screen to join a open Wi-Fi [CHAR LIMIT=NONE] -->
+ <string name="wifi_dpp_scan_open_network_qr_code_with_another_device">Scan this QR code to connect to \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
<!-- Hint for QR code detection [CHAR LIMIT=NONE] -->
<string name="wifi_dpp_could_not_detect_valid_qr_code">Couldn\u2019t read QR code. Re-center code and try again</string>
<!-- Hint for Wi-Fi DPP handshake failure [CHAR LIMIT=NONE] -->
@@ -2166,8 +2168,16 @@
<string name="wifi_dpp_connecting">Connecting\u2026</string>
<!-- Title for the fragment to show that the QR code is for sharing Wi-Fi hotspot network [CHAR LIMIT=50] -->
<string name="wifi_dpp_share_hotspot">Share hotspot</string>
- <!-- Hint for the user to share Wi-Fi hotspot network [CHAR LIMIT=NONE] -->
- <string name="wifi_dpp_scan_qr_code_to_share_hotspot">Scan this QR code with another device to join hotspot \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
+ <!-- Title for Wi-Fi DPP lockscreen title [CHAR LIMIT=50] -->
+ <string name="wifi_dpp_lockscreen_title">Verify it\u0027s you</string>
+ <!-- Hint for Wi-Fi password [CHAR LIMIT=50] -->
+ <string name="wifi_dpp_wifi_password">Wi\u2011Fi password: <xliff:g id="password" example="my password">%1$s</xliff:g></string>
+ <!-- Hint for Wi-Fi hotspot password [CHAR LIMIT=50] -->
+ <string name="wifi_dpp_hotspot_password">Hotspot password: <xliff:g id="password" example="my password">%1$s</xliff:g></string>
+ <!-- Label for "Connect to this network using a QR code" [CHAR LIMIT=50] -->
+ <string name="wifi_dpp_add_device">Add device</string>
+ <!-- Hint for "Add device" [CHAR LIMIT=NONE] -->
+ <string name="wifi_dpp_connect_network_using_qr_code">Connect to this network using a QR code</string>
<!-- Label for the try again button [CHAR LIMIT=20]-->
<string name="retry">Retry</string>
<!-- Label for the check box to share a network with other users on the same device -->
@@ -3945,8 +3955,6 @@
<string name="lockpassword_choose_your_pattern_header_for_face">To use face authentication, set pattern</string>
<!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pin_header_for_face">To use face authentication, set PIN</string>
- <!-- Message on Wi-Fi Sharing screen [CHAR LIMIT=NONE] -->
- <string name="wifi_sharing_message">Your Wi\u2011Fi name and password for \"<xliff:g id="SSID" example="GoogleGuest">%1$s</xliff:g>\" will be shared.</string>
<!-- Message to be used to explain the user that he needs to enter his pattern to continue a
particular operation. [CHAR LIMIT=70]-->
@@ -5268,11 +5276,13 @@
<!-- Summary for the battery high usage tip, which presents battery may run out earlier [CHAR LIMIT=NONE] -->
<string name="battery_tip_high_usage_summary">Battery may run out earlier than usual</string>
<!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
- <string name="battery_tip_dialog_message" product="default">Your phone has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+ <string name="battery_tip_dialog_message" product="default">Your phone has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
<!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
- <string name="battery_tip_dialog_message" product="tablet">Your tablet has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+ <string name="battery_tip_dialog_message" product="tablet">Your tablet has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
<!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
- <string name="battery_tip_dialog_message" product="device">Your device has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+ <string name="battery_tip_dialog_message" product="device">Your device has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
+ <!-- Footer message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
+ <string name="battery_tip_dialog_message_footer">Includes high-power background activity</string>
<!-- Title for restricted app preference, showing how many app need to be restricted [CHAR LIMIT=NONE] -->
<plurals name="battery_tip_restrict_title">
<item quantity="one">Restrict %1$d app</item>
@@ -9801,6 +9811,9 @@
<!-- [CHAR LIMIT=25] Title of developer tile to toggle winscope trace -->
<string name="winscope_trace_quick_settings_title">Winscope Trace</string>
+ <!-- [CHAR LIMIT=25] Title of developer tile to toggle sensors -->
+ <string name="sensors_off_quick_settings_title">Sensors Off</string>
+
<!-- [CHAR LIMIT=60] Title of work profile setting page -->
<string name="managed_profile_settings_title">Work profile settings</string>
<!-- [CHAR LIMIT=60] The preference title for enabling cross-profile remote contact search -->
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 097ffe2..81b70b5 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -140,7 +140,7 @@
if (!mHasPassword) {
// No password registered, launch into enrollment wizard.
launchChooseLock();
- } else {
+ } else if (!mLaunchedConfirmLock || mToken == null) {
launchConfirmLock(getConfirmLockTitleResId(), getChallenge());
}
}
diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java
index 5edbc70..bb791ab 100644
--- a/src/com/android/settings/development/qstile/DevelopmentTiles.java
+++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java
@@ -16,9 +16,12 @@
package com.android.settings.development.qstile;
+import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.hardware.SensorPrivacyManager;
+import android.app.KeyguardManager;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
@@ -38,6 +41,8 @@
import com.android.internal.app.LocalePicker;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
import com.android.settingslib.development.SystemPropPoker;
@@ -273,4 +278,45 @@
}
}
}
-}
\ No newline at end of file
+
+ /**
+ * Tile to toggle sensors off to control camera, mic, and sensors managed by the SensorManager.
+ */
+ public static class SensorsOff extends DevelopmentTiles {
+ private Context mContext;
+ private SensorPrivacyManager mSensorPrivacyManager;
+ private KeyguardManager mKeyguardManager;
+ private MetricsFeatureProvider mMetricsFeatureProvider;
+ private boolean mIsEnabled;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mContext = getApplicationContext();
+ mSensorPrivacyManager = (SensorPrivacyManager) mContext.getSystemService(
+ Context.SENSOR_PRIVACY_SERVICE);
+ mIsEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
+ mMetricsFeatureProvider = FeatureFactory.getFactory(
+ mContext).getMetricsFeatureProvider();
+ mKeyguardManager = (KeyguardManager) mContext.getSystemService(
+ Context.KEYGUARD_SERVICE);
+ }
+
+ @Override
+ protected boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ @Override
+ public void setIsEnabled(boolean isEnabled) {
+ // Don't allow sensors to be reenabled from the lock screen.
+ if (mIsEnabled && mKeyguardManager.isKeyguardLocked()) {
+ return;
+ }
+ mMetricsFeatureProvider.action(getApplicationContext(), SettingsEnums.QS_SENSOR_PRIVACY,
+ isEnabled);
+ mIsEnabled = isEnabled;
+ mSensorPrivacyManager.setSensorPrivacy(isEnabled);
+ }
+ }
+}
diff --git a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java b/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java
deleted file mode 100644
index e9d03d7..0000000
--- a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.gestures;
-
-import static android.provider.Settings.Secure.DOZE_WAKE_SCREEN_GESTURE;
-
-import android.annotation.UserIdInt;
-import android.content.Context;
-import android.hardware.display.AmbientDisplayConfiguration;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.aware.AwareFeatureProvider;
-import com.android.settings.overlay.FeatureFactory;
-
-public class WakeScreenGesturePreferenceController extends GesturePreferenceController {
-
- private static final int ON = 1;
- private static final int OFF = 0;
-
- private static final String PREF_KEY_VIDEO = "gesture_wake_screen_video";
-
- private final AwareFeatureProvider mFeatureProvider;
- private AmbientDisplayConfiguration mAmbientConfig;
- @UserIdInt
- private final int mUserId;
-
- public WakeScreenGesturePreferenceController(Context context, String key) {
- super(context, key);
- mUserId = UserHandle.myUserId();
- mFeatureProvider = FeatureFactory.getFactory(context).getAwareFeatureProvider();
- }
-
- @Override
- public int getAvailabilityStatus() {
- if (!getAmbientConfig().wakeScreenGestureAvailable()
- || !mFeatureProvider.isSupported(mContext)) {
- return UNSUPPORTED_ON_DEVICE;
- }
-
- if (!mFeatureProvider.isEnabled(mContext)) {
- return CONDITIONALLY_UNAVAILABLE;
- }
-
- return getAmbientConfig().alwaysOnEnabled(mUserId)
- ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
- }
-
- @Override
- protected boolean canHandleClicks() {
- return getAmbientConfig().alwaysOnEnabled(mUserId);
- }
-
- @Override
- public boolean isSliceable() {
- return TextUtils.equals(getPreferenceKey(), "gesture_wake_screen");
- }
-
- @Override
- protected String getVideoPrefKey() {
- return PREF_KEY_VIDEO;
- }
-
- @Override
- public boolean isChecked() {
- return getAmbientConfig().wakeScreenGestureEnabled(mUserId);
- }
-
- @Override
- public boolean setChecked(boolean isChecked) {
- return Settings.Secure.putInt(mContext.getContentResolver(), DOZE_WAKE_SCREEN_GESTURE,
- isChecked ? ON : OFF);
- }
-
- private AmbientDisplayConfiguration getAmbientConfig() {
- if (mAmbientConfig == null) {
- mAmbientConfig = new AmbientDisplayConfiguration(mContext);
- }
-
- return mAmbientConfig;
- }
-
- @VisibleForTesting
- public void setConfig(AmbientDisplayConfiguration config) {
- mAmbientConfig = config;
- }
-}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 7df322d..92108f0 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -43,6 +43,8 @@
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.ArrayList;
import java.util.List;
@@ -98,7 +100,6 @@
mLifecycleObservers = new ArrayList<>();
mControllerRendererPool = new ControllerRendererPool();
mLifecycle.addObserver(this);
-
if (savedInstanceState == null) {
mIsFirstLaunch = true;
mSavedCards = null;
@@ -240,6 +241,21 @@
outState.putStringArrayList(KEY_CONTEXTUAL_CARDS, cards);
}
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ // Duplicate a list to avoid java.util.ConcurrentModificationException.
+ final List<ContextualCard> cards = new ArrayList<>(mContextualCards);
+ for (ContextualCard card : cards) {
+ final ContextualCardController controller = mControllerRendererPool
+ .getController(mContext, card.getCardType());
+ if (hasWindowFocus && controller instanceof OnStart) {
+ ((OnStart) controller).onStart();
+ }
+ if (!hasWindowFocus && controller instanceof OnStop) {
+ ((OnStop) controller).onStop();
+ }
+ }
+ }
+
public ControllerRendererPool getControllerRendererPool() {
return mControllerRendererPool;
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index 72ddb50..bd25866 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -27,17 +27,17 @@
import androidx.loader.app.LoaderManager;
import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.overlay.FeatureFactory;
-public class ContextualCardsFragment extends InstrumentedFragment {
+public class ContextualCardsFragment extends InstrumentedFragment implements
+ FocusRecyclerView.FocusListener {
private static final String TAG = "ContextualCardsFragment";
- private RecyclerView mCardsContainer;
+ private FocusRecyclerView mCardsContainer;
private GridLayoutManager mLayoutManager;
private ContextualCardsAdapter mContextualCardsAdapter;
private ContextualCardManager mContextualCardManager;
@@ -72,11 +72,17 @@
this /* lifecycleOwner */, mContextualCardManager);
mCardsContainer.setAdapter(mContextualCardsAdapter);
mContextualCardManager.setListener(mContextualCardsAdapter);
+ mCardsContainer.setListener(this);
return rootView;
}
@Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ mContextualCardManager.onWindowFocusChanged(hasWindowFocus);
+ }
+
+ @Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_HOMEPAGE;
}
diff --git a/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java b/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java
new file mode 100644
index 0000000..a2ec9af
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java
@@ -0,0 +1,36 @@
+package com.android.settings.homepage.contextualcards;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+public class FocusRecyclerView extends RecyclerView {
+
+ private FocusListener mListener;
+
+ public FocusRecyclerView(Context context) {
+ super(context);
+ }
+
+ public FocusRecyclerView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if (mListener != null) {
+ mListener.onWindowFocusChanged(hasWindowFocus);
+ }
+ }
+
+ public void setListener(FocusListener listener) {
+ mListener = listener;
+ }
+
+ public interface FocusListener {
+ void onWindowFocusChanged(boolean hasWindowFocus);
+ }
+}
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index 28c6cb7..e9057e6 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -138,6 +138,10 @@
.setOnItemClickListener(
(parent, view, position, id) -> this.onClick(dialog, position));
+ // Don't dismiss dialog when touching outside. User report it is easy to touch outside.
+ // This causes dialog to close. Which is concerned as a bad UX (b/128877712).
+ dialog.setCanceledOnTouchOutside(false);
+
dialog.setOnShowListener((dialogInterface) -> {
// Replace NeutralButton onClickListener to avoid closing dialog
final Button neutralBtn = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index f328dba..cf59dbd 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -771,14 +771,7 @@
* Share the wifi network with QR code.
*/
private void shareNetwork() {
- final String title = mContext.getString(
- R.string.lockpassword_confirm_your_pattern_header);
- final String description = String.format(
- mContext.getString(R.string.wifi_sharing_message),
- mAccessPoint.getSsidStr());
-
- WifiDppUtils.showLockScreen(mContext, title, description,
- () -> launchWifiDppConfiguratorActivity());
+ WifiDppUtils.showLockScreen(mContext, () -> launchWifiDppConfiguratorActivity());
}
/**
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index 2cd5e23..4e6a0d6 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -29,6 +30,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
+import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.wifi.qrcode.QrCodeGenerator;
@@ -43,6 +45,7 @@
private static final String TAG = "WifiDppQrCodeGeneratorFragment";
private ImageView mQrCodeView;
+ private TextView mPasswordView;
private String mQrCode;
@Override
@@ -138,12 +141,27 @@
final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
if (wifiNetworkConfig.isHotspot()) {
mTitle.setText(R.string.wifi_dpp_share_hotspot);
- mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_to_share_hotspot,
- wifiNetworkConfig.getSsid()));
} else {
mTitle.setText(R.string.wifi_dpp_share_wifi);
+ }
+
+ final String password = wifiNetworkConfig.getPreSharedKey();
+ mPasswordView = view.findViewById(R.id.password);
+ if (TextUtils.isEmpty(password)) {
+ mSummary.setText(getString(
+ R.string.wifi_dpp_scan_open_network_qr_code_with_another_device,
+ wifiNetworkConfig.getSsid()));
+
+ mPasswordView.setVisibility(View.GONE);
+ } else {
mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
wifiNetworkConfig.getSsid()));
+
+ if (wifiNetworkConfig.isHotspot()) {
+ mPasswordView.setText(getString(R.string.wifi_dpp_hotspot_password, password));
+ } else {
+ mPasswordView.setText(getString(R.string.wifi_dpp_wifi_password, password));
+ }
}
mQrCode = wifiNetworkConfig.getQrCode();
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index fe7af27..bf78b3f 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -29,6 +29,8 @@
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
+import com.android.settings.R;
+
import com.android.settingslib.wifi.AccessPoint;
import java.util.List;
@@ -273,13 +275,10 @@
* user of the device.
*
* @param context The {@code Context} used to get {@code KeyguardManager} service
- * @param title The title on lock screen
- * @param description The description on lock screen
* @param successRunnable The {@code Runnable} which will be executed if the user does not setup
* device security or if lock screen is unlocked
*/
- public static void showLockScreen(Context context, String title, String description,
- Runnable successRunnable) {
+ public static void showLockScreen(Context context, Runnable successRunnable) {
final KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(
Context.KEYGUARD_SERVICE);
@@ -299,8 +298,7 @@
};
final BiometricPrompt.Builder builder = new BiometricPrompt.Builder(context)
- .setTitle(title)
- .setDescription(description);
+ .setTitle(context.getText(R.string.wifi_dpp_lockscreen_title));
if (keyguardManager.isDeviceSecure()) {
builder.setDeviceCredentialAllowed(true);
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
index 10f3e56..b7ddcae 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
@@ -104,13 +104,7 @@
}
private void shareHotspotNetwork(Intent intent) {
- final String title = mContext.getString(
- R.string.lockpassword_confirm_your_pattern_header);
- final String description = String.format(
- mContext.getString(R.string.wifi_sharing_message), mSSID);
-
- WifiDppUtils.showLockScreen(mContext, title, description,
- () -> mContext.startActivity(intent));
+ WifiDppUtils.showLockScreen(mContext, () -> mContext.startActivity(intent));
}
@VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java
deleted file mode 100644
index 471914a..0000000
--- a/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.gestures;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
-import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.hardware.display.AmbientDisplayConfiguration;
-
-import com.android.settings.aware.AwareFeatureProvider;
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class WakeScreenGesturePreferenceControllerTest {
-
- private static final String KEY_WAKE_SCREEN = "gesture_wake_screen";
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private Context mContext;
- @Mock
- private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
- private WakeScreenGesturePreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- AwareFeatureProvider featureProvider =
- FakeFeatureFactory.setupForTest().getAwareFeatureProvider();
- when(featureProvider.isSupported(any())).thenReturn(true);
- when(featureProvider.isEnabled(any())).thenReturn(true);
- mController = new WakeScreenGesturePreferenceController(mContext, KEY_WAKE_SCREEN);
- mController.setConfig(mAmbientDisplayConfiguration);
- }
-
- @Test
- public void testIsChecked_configIsSet_shouldReturnTrue() {
- // Set the setting to be enabled.
- when(mAmbientDisplayConfiguration.wakeScreenGestureEnabled(anyInt())).thenReturn(true);
- assertThat(mController.isChecked()).isTrue();
- }
-
- @Test
- public void testIsChecked_configIsNotSet_shouldReturnFalse() {
- // Set the setting to be disabled.
- when(mAmbientDisplayConfiguration.wakeScreenGestureEnabled(anyInt())).thenReturn(false);
- assertThat(mController.isChecked()).isFalse();
- }
-
- @Test
- public void getAvailabilityStatus_gestureNotSupported_UNSUPPORTED_ON_DEVICE() {
- when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
- when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(false);
- final int availabilityStatus = mController.getAvailabilityStatus();
-
- assertThat(availabilityStatus).isEqualTo(UNSUPPORTED_ON_DEVICE);
- }
-
- @Test
- public void getAvailabilityStatus_gestureSupported_AVAILABLE() {
- when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
- when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(true);
- final int availabilityStatus = mController.getAvailabilityStatus();
-
- assertThat(availabilityStatus).isEqualTo(AVAILABLE);
- }
-
- @Test
- public void getAvailabilityStatus_gestureSupported_DISABLED_DEPENDENT_SETTING() {
- when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false);
- when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(true);
- final int availabilityStatus = mController.getAvailabilityStatus();
-
- assertThat(availabilityStatus).isEqualTo(DISABLED_DEPENDENT_SETTING);
- }
-
- @Test
- public void canHandleClicks_onlyWhenAlwaysOn() {
- when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false);
- assertThat(mController.canHandleClicks()).isEqualTo(false);
-
- reset(mAmbientDisplayConfiguration);
- when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
- assertThat(mController.canHandleClicks()).isEqualTo(true);
- }
-
- @Test
- public void isSliceableCorrectKey_returnsTrue() {
- final WakeScreenGesturePreferenceController controller =
- new WakeScreenGesturePreferenceController(mContext, "gesture_wake_screen");
- assertThat(controller.isSliceable()).isTrue();
- }
-
- @Test
- public void isSliceableIncorrectKey_returnsFalse() {
- final WakeScreenGesturePreferenceController controller =
- new WakeScreenGesturePreferenceController(mContext, "bad_key");
- assertThat(controller.isSliceable()).isFalse();
- }
-}