Snap for 7918267 from f1a30d7696 to tm-release

Change-Id: If32b08e9678c7be51e84e4673ddd49f1d1670069
This commit is contained in:
Android Build Coastguard Worker
2021-11-16 02:08:52 +00:00
12 changed files with 351 additions and 67 deletions

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?attr/fingerprint_layout_theme">
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:clipToPadding="false"
android:clipChildren="false">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/illustration_lottie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerInside"
app:lottie_imageAssetsFolder="images"
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_rawRes="@raw/fingerprint_edu_lottie"/>
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/illustration_lottie_portrait"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:visibility="gone"
app:lottie_imageAssetsFolder="images"
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_rawRes="@raw/fingerprint_edu_lottie_portrait"/>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

View File

View File

@@ -13328,6 +13328,11 @@
<!-- Wallet (formerly Cards and passes) summary [CHAR LIMIT=NONE] -->
<string name="lockscreen_privacy_wallet_summary">Allow access to wallet from lock screen and quick settings</string>
<!-- QR Code Scanner toggle name [CHAR LIMIT=60] -->
<string name="lockscreen_privacy_qr_code_scanner_setting_toggle">Show QR Code Scanner</string>
<!-- QR Code Scanner summary [CHAR LIMIT=NONE] -->
<string name="lockscreen_privacy_qr_code_scanner_summary">Allow access to QR code scanner from lock screen</string>
<!-- Device controls toggle name [CHAR LIMIT=60] -->
<string name="lockscreen_privacy_controls_setting_toggle">Show device controls</string>
<!-- Device controls summary [CHAR LIMIT=NONE] -->

View File

@@ -51,6 +51,12 @@
android:summary="@string/lockscreen_privacy_wallet_summary"
settings:controller="com.android.settings.display.WalletPrivacyPreferenceController" />
<SwitchPreference
android:key="lock_screen_show_qr_scanner"
android:title="@string/lockscreen_privacy_qr_code_scanner_setting_toggle"
android:summary="@string/lockscreen_privacy_qr_code_scanner_summary"
settings:controller="com.android.settings.display.QRCodeScannerPreferenceController" />
<SwitchPreference
android:key="lockscreen_privacy_controls_switch"
android:title="@string/lockscreen_privacy_controls_setting_toggle"

View File

@@ -21,13 +21,14 @@ import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.Nullable;
import com.airbnb.lottie.LottieAnimationView;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
@@ -35,6 +36,7 @@ import com.android.settings.biometrics.BiometricEnrollSidecar;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.airbnb.lottie.LottieAnimationView;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
@@ -52,6 +54,10 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
private FingerprintEnrollSidecar mSidecar;
private boolean mNextClicked;
private boolean mCanAssumeUdfps;
private boolean mCanAssumeSidefps;
private OrientationEventListener mOrientationEventListener;
private int mPreviousRotation = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -61,6 +67,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
final List<FingerprintSensorPropertiesInternal> props =
fingerprintManager.getSensorPropertiesInternal();
mCanAssumeUdfps = props != null && props.size() == 1 && props.get(0).isAnyUdfpsType();
mCanAssumeSidefps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType();
setContentView(getContentView());
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
mFooterBarMixin.setSecondaryButton(
@@ -72,6 +79,8 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
.build()
);
listenOrientationEvent();
if (mCanAssumeUdfps) {
setHeaderText(R.string.security_settings_udfps_enroll_find_sensor_title);
setDescriptionText(R.string.security_settings_udfps_enroll_find_sensor_message);
@@ -90,6 +99,28 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
lottieAnimationView.setAnimation(R.raw.udfps_edu_a11y_lottie);
}
} else if (mCanAssumeSidefps) {
setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
setDescriptionText(R.string.security_settings_fingerprint_enroll_find_sensor_message);
final LottieAnimationView lottieAnimationView = findViewById(R.id.illustration_lottie);
final LottieAnimationView lottieAnimationViewPortrait =
findViewById(R.id.illustration_lottie_portrait);
final int rotation = getApplicationContext().getDisplay().getRotation();
switch(rotation) {
case Surface.ROTATION_90:
lottieAnimationView.setVisibility(View.GONE);
lottieAnimationViewPortrait.setVisibility(View.VISIBLE);
break;
case Surface.ROTATION_270:
lottieAnimationView.setVisibility(View.GONE);
lottieAnimationViewPortrait.setVisibility(View.VISIBLE);
lottieAnimationViewPortrait.setRotation(180);
break;
default:
lottieAnimationView.setVisibility(View.VISIBLE);
lottieAnimationViewPortrait.setVisibility(View.GONE);
break;
}
} else {
setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
setDescriptionText(R.string.security_settings_fingerprint_enroll_find_sensor_message);
@@ -145,6 +176,8 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
protected int getContentView() {
if (mCanAssumeUdfps) {
return R.layout.udfps_enroll_find_sensor_layout;
} else if (mCanAssumeSidefps) {
return R.layout.sfps_enroll_find_sensor_layout;
}
return R.layout.fingerprint_enroll_find_sensor;
}
@@ -220,6 +253,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
@Override
protected void onDestroy() {
stopListenOrientationEvent();
super.onDestroy();
if (mAnimation != null) {
mAnimation.stopAnimation();
@@ -297,4 +331,37 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase implements
public int getMetricsCategory() {
return SettingsEnums.FINGERPRINT_FIND_SENSOR;
}
private void listenOrientationEvent() {
if (!mCanAssumeSidefps) {
// Do nothing if the device doesn't support SideFPS.
return;
}
mOrientationEventListener = new OrientationEventListener(this) {
@Override
public void onOrientationChanged(int orientation) {
final int currentRotation = getDisplay().getRotation();
if ((mPreviousRotation == Surface.ROTATION_90
&& currentRotation == Surface.ROTATION_270) || (
mPreviousRotation == Surface.ROTATION_270
&& currentRotation == Surface.ROTATION_90)) {
mPreviousRotation = currentRotation;
recreate();
}
}
};
mOrientationEventListener.enable();
mPreviousRotation = getDisplay().getRotation();
}
private void stopListenOrientationEvent() {
if (!mCanAssumeSidefps) {
// Do nothing if the device doesn't support SideFPS.
return;
}
if (mOrientationEventListener != null) {
mOrientationEventListener.disable();
}
mOrientationEventListener = null;
}
}

View File

@@ -22,7 +22,6 @@ import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.location.LocationServices;
import com.android.settings.location.RecentLocationAccessSeeAllFragment;
import java.util.Map;
@@ -43,8 +42,6 @@ public class ProfileFragmentBridge {
ProfileSelectAccountFragment.class.getName());
FRAGMENT_MAP.put(ManageApplications.class.getName(),
ProfileSelectManageApplications.class.getName());
FRAGMENT_MAP.put(RecentLocationAccessSeeAllFragment.class.getName(),
ProfileSelectRecentLocationAccessFragment.class.getName());
FRAGMENT_MAP.put(LocationServices.class.getName(),
ProfileSelectLocationServicesFragment.class.getName());
FRAGMENT_MAP.put(StorageDashboardFragment.class.getName(),

View File

@@ -1,46 +0,0 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.dashboard.profileselector;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import com.android.settings.location.RecentLocationAccessSeeAllFragment;
/**
* Recent location request page for personal/managed profile.
*/
public class ProfileSelectRecentLocationAccessFragment extends ProfileSelectFragment {
@Override
public Fragment[] getFragments() {
final Bundle workOnly = new Bundle();
workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
final Fragment workFragment = new RecentLocationAccessSeeAllFragment();
workFragment.setArguments(workOnly);
final Bundle personalOnly = new Bundle();
personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
final Fragment personalFragment = new RecentLocationAccessSeeAllFragment();
personalFragment.setArguments(personalOnly);
return new Fragment[]{
personalFragment, //0
workFragment
};
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.display;
import static android.provider.Settings.Secure.SHOW_QR_CODE_SCANNER_SETTING;
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.provider.Settings;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
/**
* Preference controller for enabling/disabling QR code scanner button on lock screen.
*/
public class QRCodeScannerPreferenceController extends TogglePreferenceController {
private static final String SETTING_KEY = Settings.Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER;
private final ContentObserver mSettingsObserver;
private final ContentResolver mContentResolver;
private Preference mPreference;
public QRCodeScannerPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mContentResolver = context.getContentResolver();
mSettingsObserver = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange, Uri uri) {
updateState(mPreference);
}
};
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
/** Called when activity starts being displayed to user. */
@OnLifecycleEvent(ON_START)
public void onStart() {
mContentResolver.registerContentObserver(
Settings.Global.getUriFor(SHOW_QR_CODE_SCANNER_SETTING), false,
mSettingsObserver);
}
/** Called when activity stops being displayed to user. */
@OnLifecycleEvent(ON_STOP)
public void onStop() {
mContentResolver.unregisterContentObserver(mSettingsObserver);
}
@Override
public boolean isChecked() {
return Settings.Secure.getInt(mContext.getContentResolver(), SETTING_KEY, 0) != 0;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Secure.putInt(mContext.getContentResolver(), SETTING_KEY,
isChecked ? 1 : 0);
}
@Override
public int getAvailabilityStatus() {
return isScannerActivityAvailable() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
refreshSummary(preference);
}
@Override
public int getSliceHighlightMenuRes() {
return R.string.menu_key_display;
}
private boolean isScannerActivityAvailable() {
return Settings.Secure.getString(mContext.getContentResolver(),
SHOW_QR_CODE_SCANNER_SETTING) != null;
}
}

View File

@@ -24,7 +24,6 @@ import android.view.MenuItem;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
@@ -52,13 +51,8 @@ public class RecentLocationAccessSeeAllFragment extends DashboardFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
mController = use(RecentLocationAccessSeeAllPreferenceController.class);
mController.init(this);
if (profileType != 0) {
mController.setProfileType(profileType);
}
}
@Override

View File

@@ -40,7 +40,6 @@ public class RecentLocationAccessSeeAllPreferenceController
private final RecentAppOpsAccess mRecentLocationAccesses;
private boolean mShowSystem = false;
private Preference mPreference;
private int mType = ProfileSelectFragment.ProfileType.ALL;
public RecentLocationAccessSeeAllPreferenceController(Context context, String key) {
super(context, key);
@@ -68,7 +67,8 @@ public class RecentLocationAccessSeeAllPreferenceController
final List<RecentAppOpsAccess.Access> recentLocationAccesses = new ArrayList<>();
for (RecentAppOpsAccess.Access access : mRecentLocationAccesses.getAppListSorted(
mShowSystem)) {
if (isRequestMatchesProfileType(userManager, access, mType)) {
if (isRequestMatchesProfileType(
userManager, access, ProfileSelectFragment.ProfileType.ALL)) {
recentLocationAccesses.add(access);
}
}
@@ -89,15 +89,6 @@ public class RecentLocationAccessSeeAllPreferenceController
}
}
/**
* Initialize {@link ProfileSelectFragment.ProfileType} of the controller
*
* @param type {@link ProfileSelectFragment.ProfileType} of the controller.
*/
public void setProfileType(@ProfileSelectFragment.ProfileType int type) {
mType = type;
}
/**
* Set the value of {@link #mShowSystem}.
*/

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.display;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.Preference;
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 QRCodeScannerPreferenceControllerTest {
private static final String TEST_KEY = "test_key";
private static final String SETTING_KEY = Settings.Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER;
private static final String DEFAULT_COMPONENT =
Settings.Secure.SHOW_QR_CODE_SCANNER_SETTING;
private Context mContext;
private ContentResolver mContentResolver;
private QRCodeScannerPreferenceController mController;
@Mock
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContentResolver = mContext.getContentResolver();
mController = new QRCodeScannerPreferenceController(mContext, TEST_KEY);
}
@Test
public void isChecked_SettingIs1_returnTrue() {
Settings.Secure.putInt(mContentResolver, SETTING_KEY, 1);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void isChecked_SettingIs0_returnFalse() {
Settings.Secure.putInt(mContentResolver, SETTING_KEY, 0);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void isChecked_SettingIsNotSet_returnFalse() {
Settings.Secure.putString(mContentResolver, SETTING_KEY, null);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void setChecked_true_SettingIsNot0() {
mController.setChecked(true);
assertThat(Settings.Secure.getInt(mContentResolver, SETTING_KEY, 0)).isNotEqualTo(0);
}
@Test
public void setChecked_false_SettingIs0() {
mController.setChecked(false);
assertThat(Settings.Secure.getInt(mContentResolver, SETTING_KEY, 0)).isEqualTo(0);
}
@Test
public void getAvailabilityStatus_defaultComponentNotSet() {
Settings.Secure.putString(mContext.getContentResolver(), DEFAULT_COMPONENT, null);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_defaultComponentSet() {
Settings.Secure.putString(mContext.getContentResolver(), DEFAULT_COMPONENT, "abc");
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
}