diff --git a/res/values/strings.xml b/res/values/strings.xml index 6ff3a00df8f..111d9017789 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4894,49 +4894,57 @@ When magnification is turned on, you can zoom in on your screen.\n\nTo zoom, start magnification, then tap anywhere on the screen.\n\n\nTo zoom temporarily, start magnification, then touch & hold anywhere on the screen.\n\n\nYou can’t zoom in on the keyboard or navigation bar. - + Use accessibility button to open - + + Hold volume key to open + + Triple tap screen to open + Use gesture to open - + Use new accessibility gesture - - To turn this service on or off, tap the accessibility button %s on the bottom of your screen.\n\nTo switch between services, touch & hold the accessibility button. - - To turn this service on or off, swipe up from the bottom of the screen with two fingers.\n\nTo switch between services, swipe up with two fingers and hold. - - To turn this service on or off, swipe up from the bottom of the screen with three fingers.\n\nTo switch between services, swipe up with three fingers and hold. - - To turn an accessibility service on or off, swipe up from the bottom of the screen with two fingers.\n\nTo switch between services, swipe up with two fingers and hold. - - To turn an accessibility service on or off, swipe up from the bottom of the screen with three fingers.\n\nTo switch between services, swipe up with three fingers and hold. - + + To turn this app on or off, tap the accessibility button %s on the bottom of your screen.\n\nTo switch between apps, touch & hold the accessibility button. + + To turn this app on or off, press & hold both volume keys for 1 second. + + To start and stop magnification, triple-tap anywhere on your screen. + + To turn this app on or off, swipe up from the bottom of the screen with two fingers.\n\nTo switch between apps, swipe up with two fingers and hold. + + To turn this app on or off, swipe up from the bottom of the screen with three fingers.\n\nTo switch between apps, swipe up with three fingers and hold. + + To turn an accessibility app on or off, swipe up from the bottom of the screen with two fingers.\n\nTo switch between apps, swipe up with two fingers and hold. + + To turn an accessibility app on or off, swipe up from the bottom of the screen with three fingers.\n\nTo switch between apps, swipe up with three fingers and hold. + Got it %1$s shortcut - + Accessibility Button - + Swipe up with 2 fingers - + Swipe up with 3 fingers Tap accessibility button - + Tap the accessibility button %s at the bottom of your screen - + Swipe up from the bottom of the screen with 2 fingers - + Swipe up from the bottom of the screen with 3 fingers - + Hold volume keys - + Press & hold both volume keys for 1 second - + Triple-tap screen - + Quickly tap screen 3 times. This shortcut may slow down your device. - + Advanced The Accessibility button is set to %1$s. To use magnification, touch & hold the Accessibility button, then select magnification. @@ -6997,7 +7005,7 @@ Expand settings for application - Tap & pay + Contactless payments How it works diff --git a/src/com/android/settings/development/EnhancedConnectivityPreferenceController.java b/src/com/android/settings/development/EnhancedConnectivityPreferenceController.java index 2dbd7d1ee2b..dc6597384d2 100644 --- a/src/com/android/settings/development/EnhancedConnectivityPreferenceController.java +++ b/src/com/android/settings/development/EnhancedConnectivityPreferenceController.java @@ -37,7 +37,7 @@ public class EnhancedConnectivityPreferenceController extends @VisibleForTesting static final int ENHANCED_CONNECTIVITY_ON = 1; - // default is enhanced connectivity disabled. + // default is enhanced connectivity enabled. @VisibleForTesting static final int ENHANCED_CONNECTIVITY_OFF = 0; @@ -65,7 +65,7 @@ public class EnhancedConnectivityPreferenceController extends public void updateState(Preference preference) { final int enhancedConnectivityEnabled = Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.ENHANCED_CONNECTIVITY_ENABLED, - ENHANCED_CONNECTIVITY_OFF); + ENHANCED_CONNECTIVITY_ON); ((SwitchPreference) mPreference).setChecked( enhancedConnectivityEnabled == ENHANCED_CONNECTIVITY_ON); } @@ -75,7 +75,7 @@ public class EnhancedConnectivityPreferenceController extends super.onDeveloperOptionsSwitchDisabled(); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ENHANCED_CONNECTIVITY_ENABLED, - ENHANCED_CONNECTIVITY_OFF); - ((SwitchPreference) mPreference).setChecked(false); + ENHANCED_CONNECTIVITY_ON); + ((SwitchPreference) mPreference).setChecked(true); } } diff --git a/src/com/android/settings/network/ims/ImsQueryController.java b/src/com/android/settings/network/ims/ImsQueryController.java index 8fdad4004fe..068a80537b9 100644 --- a/src/com/android/settings/network/ims/ImsQueryController.java +++ b/src/com/android/settings/network/ims/ImsQueryController.java @@ -20,6 +20,7 @@ import android.telephony.AccessNetworkConstants; import android.telephony.SubscriptionManager; import android.telephony.ims.ImsException; import android.telephony.ims.ImsMmTelManager; +import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; @@ -84,4 +85,20 @@ abstract class ImsQueryController { boolean isProvisionedOnDevice(int subId) { return (new ImsQueryProvisioningStat(subId, mCapability, mTech)).query(); } + + @VisibleForTesting + boolean isServiceStateReady(int subId) throws InterruptedException, ImsException, + IllegalArgumentException { + if (!SubscriptionManager.isValidSubscriptionId(subId)) { + return false; + } + + final ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(subId); + // TODO: have a shared thread pool instead of create ExecutorService + // everytime to improve performance. + final ExecutorService executor = Executors.newSingleThreadExecutor(); + final IntegerConsumer intResult = new IntegerConsumer(); + imsMmTelManager.getFeatureState(executor, intResult); + return (intResult.get(TIMEOUT_MILLIS) == ImsFeature.STATE_READY); + } } diff --git a/src/com/android/settings/network/ims/IntegerConsumer.java b/src/com/android/settings/network/ims/IntegerConsumer.java new file mode 100644 index 00000000000..02c82275a86 --- /dev/null +++ b/src/com/android/settings/network/ims/IntegerConsumer.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.network.ims; + +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +class IntegerConsumer extends Semaphore implements Consumer { + + private static final String TAG = "IntegerConsumer"; + + IntegerConsumer() { + super(0); + mValue = new AtomicInteger(); + } + + private volatile AtomicInteger mValue; + + /** + * Get boolean value reported from callback + * + * @param timeout callback waiting time in milliseconds + * @return int value reported + * @throws InterruptedException when thread get interrupted + */ + int get(long timeout) throws InterruptedException { + tryAcquire(timeout, TimeUnit.MILLISECONDS); + return mValue.get(); + } + + /** + * Implementation of {@link Consumer#accept(Integer)} + * + * @param value int reported from {@link Consumer#accept(Integer)} + */ + public void accept(Integer value) { + if (value != null) { + mValue.set(value.intValue()); + } + release(); + } +} diff --git a/src/com/android/settings/network/ims/VtQueryImsState.java b/src/com/android/settings/network/ims/VtQueryImsState.java index 60bd72988e3..c0776036bf1 100644 --- a/src/com/android/settings/network/ims/VtQueryImsState.java +++ b/src/com/android/settings/network/ims/VtQueryImsState.java @@ -20,20 +20,23 @@ import android.content.Context; import android.telecom.TelecomManager; import android.telephony.AccessNetworkConstants; import android.telephony.SubscriptionManager; +import android.telephony.ims.ImsException; import android.telephony.ims.feature.MmTelFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; +import android.util.Log; import androidx.annotation.VisibleForTesting; import com.android.ims.ImsManager; import com.android.settings.network.SubscriptionUtil; -import com.android.settings.network.telephony.MobileNetworkUtils; /** * Controller class for querying VT status */ public class VtQueryImsState extends ImsQueryController { + private static final String LOG_TAG = "VtQueryImsState"; + private Context mContext; private int mSubId; @@ -71,14 +74,25 @@ public class VtQueryImsState extends ImsQueryController { * @return true when Video Call can be performed, otherwise false */ public boolean isReadyToVideoCall() { + if (!isProvisionedOnDevice(mSubId)) { + return false; + } + final ImsManager imsManager = getImsManager(mSubId); if (imsManager == null) { return false; } - return imsManager.isVtEnabledByPlatform() - && isProvisionedOnDevice(mSubId) - && MobileNetworkUtils.isImsServiceStateReady(imsManager); + if (!imsManager.isVtEnabledByPlatform()) { + return false; + } + + try { + return isServiceStateReady(mSubId); + } catch (InterruptedException | IllegalArgumentException | ImsException exception) { + Log.w(LOG_TAG, "fail to get Vt service status. subId=" + mSubId, exception); + } + return false; } /** diff --git a/src/com/android/settings/password/BiometricFragment.java b/src/com/android/settings/password/BiometricFragment.java index bc0e5c75231..7e783227362 100644 --- a/src/com/android/settings/password/BiometricFragment.java +++ b/src/com/android/settings/password/BiometricFragment.java @@ -70,6 +70,13 @@ public class BiometricFragment extends InstrumentedFragment { }); cleanup(); } + + @Override + public void onAuthenticationFailed() { + mClientExecutor.execute(() -> { + mClientCallback.onAuthenticationFailed(); + }); + } }; private final DialogInterface.OnClickListener mNegativeButtonListener = diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java index 83368f95e0f..220b64929ad 100644 --- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java +++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java @@ -111,6 +111,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity { }); private AuthenticationCallback mAuthenticationCallback = new AuthenticationCallback() { + @Override public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { if (!mGoingToBackground) { if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED @@ -123,17 +124,24 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity { } } + @Override public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) { mTrustManager.setDeviceLockedForUser(mUserId, false); - + final boolean isStrongAuth = result.getAuthenticationType() + == BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL; ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils, mUserManager, - mUserId); + mDevicePolicyManager, mUserId, isStrongAuth); ConfirmDeviceCredentialUtils.checkForPendingIntent( ConfirmDeviceCredentialActivity.this); setResult(Activity.RESULT_OK); finish(); } + + @Override + public void onAuthenticationFailed() { + mDevicePolicyManager.reportFailedBiometricAttempt(mUserId); + } }; private String getStringForError(int errorCode) { diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java b/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java index 11d69246206..a5febebc198 100644 --- a/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java +++ b/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.IActivityManager; +import android.app.admin.DevicePolicyManager; import android.content.Intent; import android.content.IntentSender; import android.os.RemoteException; @@ -54,8 +55,12 @@ public class ConfirmDeviceCredentialUtils { } public static void reportSuccessfulAttempt(LockPatternUtils utils, UserManager userManager, - int userId) { - utils.reportSuccessfulPasswordAttempt(userId); + DevicePolicyManager dpm, int userId, boolean isStrongAuth) { + if (isStrongAuth) { + utils.reportSuccessfulPasswordAttempt(userId); + } else { + dpm.reportSuccessfulBiometricAttempt(userId); + } if (userManager.isManagedProfile(userId)) { // Keyguard is responsible to disable StrongAuth for primary user. Disable StrongAuth // for work challenge only here. diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java index ce8813ffbad..260919dbcee 100644 --- a/src/com/android/settings/password/ConfirmLockPassword.java +++ b/src/com/android/settings/password/ConfirmLockPassword.java @@ -475,7 +475,8 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity { if (matched) { if (newResult) { ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils, - mUserManager, mEffectiveUserId); + mUserManager, mDevicePolicyManager, mEffectiveUserId, + /* isStrongAuth */ true); } startDisappearAnimation(intent); ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity()); diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java index b2afb22da96..06f3d93d3c8 100644 --- a/src/com/android/settings/password/ConfirmLockPattern.java +++ b/src/com/android/settings/password/ConfirmLockPattern.java @@ -509,7 +509,8 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { if (matched) { if (newResult) { ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils, - mUserManager, mEffectiveUserId); + mUserManager, mDevicePolicyManager, mEffectiveUserId, + /* isStrongAuth */ true); } startDisappearAnimation(intent); ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity()); diff --git a/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java b/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java index a28f9907d6b..23971e717ac 100644 --- a/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java +++ b/src/com/android/settings/wifi/ConfigureWifiEntryFragment.java @@ -71,7 +71,8 @@ public class ConfigureWifiEntryFragment extends InstrumentedFragment implements private Button mSubmitBtn; private Button mCancelBtn; private WifiEntry mWifiEntry; - private NetworkDetailsTracker mNetworkDetailsTracker; + @VisibleForTesting + NetworkDetailsTracker mNetworkDetailsTracker; private HandlerThread mWorkerThread; @Override diff --git a/tests/robotests/src/com/android/settings/development/EnhancedConnectivityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/EnhancedConnectivityPreferenceControllerTest.java index 6fd6f553850..171fc6bc5de 100644 --- a/tests/robotests/src/com/android/settings/development/EnhancedConnectivityPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/EnhancedConnectivityPreferenceControllerTest.java @@ -88,20 +88,20 @@ public class EnhancedConnectivityPreferenceControllerTest { } @Test - public void onDeveloperOptionsDisabled_shouldDisablePreference() { - mController.onDeveloperOptionsDisabled(); + public void onDeveloperOptionsDisabled_shouldEnablePreference() { + mController.onDeveloperOptionsSwitchDisabled(); verify(mPreference).setEnabled(false); - verify(mPreference).setChecked(false); + verify(mPreference).setChecked(true); - assertThat(isSettingEnabled()).isFalse(); + assertThat(isSettingEnabled()).isTrue(); } private boolean isSettingEnabled() { return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ENHANCED_CONNECTIVITY_ENABLED, - EnhancedConnectivityPreferenceController.ENHANCED_CONNECTIVITY_OFF - /* default off */) + EnhancedConnectivityPreferenceController.ENHANCED_CONNECTIVITY_ON + /* default on */) == EnhancedConnectivityPreferenceController.ENHANCED_CONNECTIVITY_ON; } } diff --git a/tests/robotests/src/com/android/settings/network/ims/MockVtQueryImsState.java b/tests/robotests/src/com/android/settings/network/ims/MockVtQueryImsState.java index 4fd7d0c6dfb..3daf6cb0f1e 100644 --- a/tests/robotests/src/com/android/settings/network/ims/MockVtQueryImsState.java +++ b/tests/robotests/src/com/android/settings/network/ims/MockVtQueryImsState.java @@ -17,6 +17,7 @@ package com.android.settings.network.ims; import android.content.Context; +import android.telephony.ims.ImsException; import com.android.ims.ImsManager; @@ -29,6 +30,7 @@ public class MockVtQueryImsState extends VtQueryImsState { private Boolean mIsTtyOnVolteEnabled; private Boolean mIsProvisionedOnDevice; private Boolean mIsEnabledByUser; + private Boolean mIsServiceStateReady; /** * Constructor @@ -68,6 +70,19 @@ public class MockVtQueryImsState extends VtQueryImsState { return super.isProvisionedOnDevice(subId); } + public void setServiceStateReady(boolean isReady) { + mIsServiceStateReady = isReady; + } + + @Override + boolean isServiceStateReady(int subId) throws InterruptedException, ImsException, + IllegalArgumentException { + if (mIsServiceStateReady != null) { + return mIsServiceStateReady; + } + return super.isServiceStateReady(subId); + } + public void setIsEnabledByUser(boolean enabled) { mIsEnabledByUser = enabled; } diff --git a/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java index c766289c2b6..04fc4b94889 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/VideoCallingPreferenceControllerTest.java @@ -27,7 +27,6 @@ import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.TelephonyManager; import android.telephony.ims.ProvisioningManager; -import android.telephony.ims.feature.ImsFeature; import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; @@ -98,7 +97,7 @@ public class VideoCallingPreferenceControllerTest { doReturn(true).when(mImsManager).isVtEnabledByPlatform(); mQueryImsState.setIsProvisionedOnDevice(true); - doReturn(ImsFeature.STATE_READY).when(mImsManager).getImsServiceState(); + mQueryImsState.setServiceStateReady(true); doReturn(true).when(mTelephonyManager).isDataEnabled(); mController.mCallState = TelephonyManager.CALL_STATE_IDLE; diff --git a/tests/robotests/src/com/android/settings/wifi/ConfigureWifiEntryFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/ConfigureWifiEntryFragmentTest.java index 1f0c3127d55..ce9d10ca99d 100644 --- a/tests/robotests/src/com/android/settings/wifi/ConfigureWifiEntryFragmentTest.java +++ b/tests/robotests/src/com/android/settings/wifi/ConfigureWifiEntryFragmentTest.java @@ -24,21 +24,17 @@ import static org.mockito.Mockito.verify; import android.app.settings.SettingsEnums; import android.os.Bundle; -import com.android.settings.testutils.shadow.ShadowConnectivityManager; +import com.android.wifitrackerlib.NetworkDetailsTracker; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; import org.robolectric.shadows.androidx.fragment.FragmentController; -// TODO(b/70983952): Can't test because b/146802959, should remove @Ignore tag after it's fixed. -@Ignore @RunWith(RobolectricTestRunner.class) -@Config(shadows = ShadowConnectivityManager.class) public class ConfigureWifiEntryFragmentTest { private static final String KEY_SSID = "key_ssid"; @@ -46,6 +42,9 @@ public class ConfigureWifiEntryFragmentTest { private ConfigureWifiEntryFragment mConfigureWifiEntryFragment; + @Mock + private NetworkDetailsTracker mNetworkDetailsTracker; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -55,6 +54,8 @@ public class ConfigureWifiEntryFragmentTest { bundle.putInt(KEY_SECURITY, 1 /* WEP */); mConfigureWifiEntryFragment = spy(new ConfigureWifiEntryFragment()); mConfigureWifiEntryFragment.setArguments(bundle); + mConfigureWifiEntryFragment.mNetworkDetailsTracker = mNetworkDetailsTracker; + FragmentController.setupFragment(mConfigureWifiEntryFragment); }