Merge "Use a boolean Consumer instead of RoleManagerCallback."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 96e3dd1..7625e78 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1245,6 +1245,10 @@
<action android:name="android.settings.PRIVACY_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.REQUEST_ENABLE_CONTENT_CAPTURE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.privacy.PrivacyDashboardFragment" />
</activity>
@@ -1575,19 +1579,12 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.FINGERPRINT_ENROLL" />
</intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
- </intent-filter>
- <meta-data android:name="com.android.settings.dismiss"
- android:value="5,9,30" />
<meta-data android:name="com.android.settings.require_feature"
android:value="android.hardware.fingerprint" />
<meta-data android:name="com.android.settings.title"
android:resource="@string/suggestion_additional_fingerprints" />
<meta-data android:name="com.android.settings.summary"
android:resource="@string/suggestion_additional_fingerprints_summary" />
- <meta-data android:name="com.android.settings.icon_tintable" android:value="true" />
</activity>
<!-- Note this must not be exported since it returns the password in the intent -->
@@ -1651,8 +1648,7 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
</intent-filter>
- <meta-data android:name="com.android.settings.dismiss"
- android:value="2,6,30" />
+ <meta-data android:name="com.android.settings.dismiss" android:value="2," />
<meta-data android:name="com.android.settings.require_feature"
android:value="android.hardware.fingerprint" />
<meta-data android:name="com.android.settings.title"
diff --git a/res/drawable/ic_face_header.xml b/res/drawable/ic_face_header.xml
index 4493d66..0bf2c07 100644
--- a/res/drawable/ic_face_header.xml
+++ b/res/drawable/ic_face_header.xml
@@ -15,8 +15,9 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:width="24dp"
+ android:height="32dp"
+ android:width="32dp"
+ android:tint="?android:attr/colorPrimary"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index 71ce0ad..a626205 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -140,6 +140,46 @@
android:labelFor="@+id/routes"/>
<EditText style="@style/vpn_value" android:id="@+id/routes"
android:hint="@string/vpn_not_used"/>
+
+ <TextView android:id="@+id/vpn_proxy_settings_title"
+ style="@style/vpn_label"
+ android:text="@string/proxy_settings_title"
+ android:labelFor="@+id/vpn_proxy_settings" />
+
+ <Spinner android:id="@+id/vpn_proxy_settings"
+ style="@style/vpn_value"
+ android:prompt="@string/proxy_settings_title"
+ android:entries="@array/vpn_proxy_settings" />
+
+ <LinearLayout
+ android:id="@+id/vpn_proxy_fields"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:visibility="gone" >
+
+ <TextView
+ style="@style/vpn_label"
+ android:text="@string/proxy_hostname_label"
+ android:labelFor="@+id/vpn_proxy_host" />
+
+ <EditText
+ android:id="@+id/vpn_proxy_host"
+ style="@style/vpn_value"
+ android:hint="@string/proxy_hostname_hint"
+ android:inputType="textNoSuggestions" />
+
+ <TextView
+ style="@style/vpn_label"
+ android:text="@string/proxy_port_label"
+ android:labelFor="@+id/vpn_proxy_port" />
+
+ <EditText
+ android:id="@+id/vpn_proxy_port"
+ style="@style/vpn_value"
+ android:hint="@string/proxy_port_hint"
+ android:inputType="number" />
+ </LinearLayout>
</LinearLayout>
<LinearLayout android:id="@+id/login"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 6a03582..dc91f22 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -931,6 +931,14 @@
<item>IPSec VPN with certificates and hybrid authentication</item>
</string-array>
+ <!-- VPN proxy settings. -->
+ <string-array name="vpn_proxy_settings">
+ <!-- No HTTP proxy is used for the current VPN [CHAR LIMIT=25] -->
+ <item>None</item>
+ <!-- Manual HTTP proxy settings are used for the current VPN [CHAR LIMIT=25] -->
+ <item>Manual</item>
+ </string-array>
+
<!-- Match this with the constants in LegacyVpnInfo. --> <skip />
<!-- Status for a VPN network. [CHAR LIMIT=100] -->
<string-array name="vpn_states">
diff --git a/res/xml/mobile_network_list.xml b/res/xml/mobile_network_list.xml
index 5bffa2f..b72540f 100644
--- a/res/xml/mobile_network_list.xml
+++ b/res/xml/mobile_network_list.xml
@@ -24,7 +24,10 @@
android:title="@string/mobile_network_list_add_more"
android:icon="@drawable/ic_menu_add"
android:order="100" >
- <intent android:action="android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
+ <intent android:action="android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION">
+ <extra android:name="android.telephony.euicc.extra.FORCE_PROVISION"
+ android:value="true"/>
+ </intent>
</Preference>
</PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/BalanceSeekBar.java b/src/com/android/settings/accessibility/BalanceSeekBar.java
index e18a593..b108e18 100644
--- a/src/com/android/settings/accessibility/BalanceSeekBar.java
+++ b/src/com/android/settings/accessibility/BalanceSeekBar.java
@@ -28,6 +28,8 @@
import android.util.AttributeSet;
import android.widget.SeekBar;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settings.R;
/**
@@ -37,14 +39,13 @@
* Updates Settings.System for balance on progress changed.
*/
public class BalanceSeekBar extends SeekBar {
- private static final String TAG = "BalanceSeekBar";
private final Context mContext;
private final Object mListenerLock = new Object();
private OnSeekBarChangeListener mOnSeekBarChangeListener;
private final OnSeekBarChangeListener mProxySeekBarListener = new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
- synchronized(mListenerLock) {
+ synchronized (mListenerLock) {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
}
@@ -53,7 +54,7 @@
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
- synchronized(mListenerLock) {
+ synchronized (mListenerLock) {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
}
@@ -79,7 +80,7 @@
// after adjusting the seekbar, notify downstream listener.
// note that progress may have been adjusted in the code above to mCenter.
- synchronized(mListenerLock) {
+ synchronized (mListenerLock) {
if (mOnSeekBarChangeListener != null) {
mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
}
@@ -88,7 +89,8 @@
};
// Percentage of max to be used as a snap to threshold
- private static final float SNAP_TO_PERCENTAGE = 0.03f;
+ @VisibleForTesting
+ static final float SNAP_TO_PERCENTAGE = 0.03f;
private final Paint mCenterMarkerPaint;
private final Rect mCenterMarkerRect;
// changed in setMax()
@@ -122,7 +124,7 @@
@Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener listener) {
- synchronized(mListenerLock) {
+ synchronized (mListenerLock) {
mOnSeekBarChangeListener = listener;
}
}
@@ -148,5 +150,10 @@
canvas.restore();
super.onDraw(canvas);
}
+
+ @VisibleForTesting
+ OnSeekBarChangeListener getProxySeekBarListener() {
+ return mProxySeekBarListener;
+ }
}
diff --git a/src/com/android/settings/accessibility/BalanceSeekBarPreference.java b/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
index a40282c..b03c8ab 100644
--- a/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
+++ b/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
@@ -34,7 +34,9 @@
/** A slider preference that directly controls audio balance **/
public class BalanceSeekBarPreference extends SeekBarPreference {
- private static final String TAG = "BalanceSeekBarPreference";
+ private static final int BALANCE_CENTER_VALUE = 100;
+ private static final int BALANCE_MAX_VALUE = 200;
+
private final Context mContext;
private BalanceSeekBar mSeekBar;
private ImageView mIconView;
@@ -62,9 +64,9 @@
final float balance = Settings.System.getFloatForUser(
mContext.getContentResolver(), Settings.System.MASTER_BALANCE,
0.f /* default */, UserHandle.USER_CURRENT);
- // Rescale balance to range 0-200 centered at 100.
- mSeekBar.setMax(200);
- mSeekBar.setProgress((int)(balance * 100.f) + 100);
+ // Rescale balance to range 0-BALANCE_MAX_VALUE centered at BALANCE_MAX_VALUE / 2.
+ mSeekBar.setMax(BALANCE_MAX_VALUE);
+ mSeekBar.setProgress((int) (balance * 100.f) + BALANCE_CENTER_VALUE);
mSeekBar.setEnabled(isEnabled());
}
}
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index 39a7a80..1b41240 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -41,19 +41,19 @@
super.onCreate(savedInstanceState);
final PackageManager pm = getApplicationContext().getPackageManager();
- Intent intent;
+ Intent intent = null;
// This logic may have to be modified on devices with multiple biometrics.
if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
intent = getFingerprintEnrollIntent();
} else if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
intent = getFaceEnrollIntent();
- } else {
- intent = new Intent();
}
- intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- startActivity(intent);
+ if (intent != null) {
+ intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ startActivity(intent);
+ }
finish();
}
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index d7f2c97..097ffe2 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -21,11 +21,14 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.storage.StorageManager;
import android.view.View;
import android.widget.TextView;
+import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.password.ChooseLockGeneric;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.SetupChooseLockGeneric;
@@ -202,7 +205,14 @@
protected Intent getChooseLockIntent() {
if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+ // Default to PIN lock in setup wizard
Intent intent = new Intent(this, SetupChooseLockGeneric.class);
+ if (StorageManager.isFileEncryptedNativeOrEmulated()) {
+ intent.putExtra(
+ LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+ intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+ }
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
return intent;
} else {
@@ -212,23 +222,21 @@
@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) {
- setResult(result, data);
+ if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP) {
+ setResult(resultCode, data);
finish();
return;
}
} else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
- if (isResultFinished) {
+ if (resultCode == RESULT_FINISHED) {
updatePasswordQuality();
mToken = data.getByteArrayExtra(
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
return;
} else {
- setResult(result, data);
+ setResult(resultCode, data);
finish();
}
} else if (requestCode == CONFIRM_REQUEST) {
@@ -236,7 +244,7 @@
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out);
} else {
- setResult(result, data);
+ setResult(resultCode, data);
finish();
}
} else if (requestCode == LEARN_MORE_REQUEST) {
@@ -249,6 +257,11 @@
finish();
}
+ protected void onSkipButtonClick(View view) {
+ setResult(RESULT_SKIP);
+ finish();
+ }
+
@Override
protected void initViews() {
super.initViews();
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 8d4c82e..5f2b675 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -60,14 +60,25 @@
mSwitchDiversity = findViewById(R.id.toggle_diversity);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
- mFooterBarMixin.setSecondaryButton(
- new FooterButton.Builder(this)
- .setText(R.string.security_settings_face_enroll_introduction_cancel)
- .setListener(this::onCancelButtonClick)
- .setButtonType(FooterButton.ButtonType.SKIP)
- .setTheme(R.style.SudGlifButton_Secondary)
- .build()
- );
+ if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.skip_label)
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.SKIP)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
+ } else {
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.security_settings_face_enroll_introduction_cancel)
+ .setListener(this::onCancelButtonClick)
+ .setButtonType(FooterButton.ButtonType.CANCEL)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
+ }
mFooterBarMixin.setPrimaryButton(
new FooterButton.Builder(this)
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index f2ffe22..6c2da07 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -23,7 +23,6 @@
public static final String AUDIO_SWITCHER_SETTINGS = "settings_audio_switcher";
public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
- public static final String WIFI_MAC_RANDOMIZATION = "settings_wifi_mac_randomization";
public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
public static final String SLICE_INJECTION = "settings_slice_injection";
public static final String MAINLINE_MODULE = "settings_mainline_module";
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index 3320be0..99fe219 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -16,11 +16,14 @@
package com.android.settings.homepage.contextualcards.slices;
+import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@@ -87,6 +90,9 @@
@Override
public Slice getSlice() {
+ // Reload theme for switching dark mode on/off
+ mContext.getTheme().applyStyle(R.style.Theme_Settings_Home, true /* force */);
+
final IconCompat icon = IconCompat.createWithResource(mContext,
com.android.internal.R.drawable.ic_settings_bluetooth);
final CharSequence title = mContext.getText(R.string.bluetooth_devices);
@@ -98,7 +104,7 @@
ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder =
new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
- .setAccentColor(Utils.getColorAccentDefaultColor(mContext));
+ .setAccentColor(COLOR_NOT_TINTED);
// Get row builders by Bluetooth devices.
final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilder();
@@ -207,13 +213,23 @@
IconCompat getBluetoothDeviceIcon(CachedBluetoothDevice device) {
final Pair<Drawable, String> pair = BluetoothUtils
.getBtClassDrawableWithDescription(mContext, device);
+ final Drawable drawable = pair.first;
- if (pair.first != null) {
- return Utils.createIconWithDrawable(pair.first);
- } else {
+ // Use default bluetooth icon if can't get icon.
+ if (drawable == null) {
return IconCompat.createWithResource(mContext,
com.android.internal.R.drawable.ic_settings_bluetooth);
}
+
+ // Tint icon: Accent color for connected state; Disable color for busy state.
+ @ColorInt int color = Utils.getColorAccentDefaultColor(mContext);
+ if (device.isBusy()) {
+ color = Utils.getDisabled(mContext,
+ Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal));
+ }
+ drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
+
+ return Utils.createIconWithDrawable(drawable);
}
private List<ListBuilder.RowBuilder> getBluetoothRowBuilder() {
@@ -227,7 +243,7 @@
.setSubtitle(bluetoothDevice.getConnectionSummary());
if (bluetoothDevice.isConnectedA2dpDevice()) {
- // For available media devices, the primary action is to active audio stream and
+ // For available media devices, the primary action is to activate audio stream and
// add setting icon to the end to link detail page.
rowBuilder.setPrimaryAction(buildMediaBluetoothAction(bluetoothDevice));
rowBuilder.addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice));
@@ -260,7 +276,7 @@
SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
return SliceAction.createDeeplink(
getBluetoothDetailIntent(bluetoothDevice),
- IconCompat.createWithResource(mContext, R.drawable.ic_settings_24dp),
+ IconCompat.createWithResource(mContext, R.drawable.ic_settings_accent),
ListBuilder.ICON_IMAGE,
bluetoothDevice.getName());
}
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index dd282c6..a1fef4c 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -29,6 +29,7 @@
import android.telephony.euicc.EuiccManager;
import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settings.widget.AddPreference;
import com.android.settingslib.Utils;
@@ -43,7 +44,8 @@
import androidx.preference.PreferenceScreen;
public class MobileNetworkSummaryController extends AbstractPreferenceController implements
- SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver {
+ SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver,
+ PreferenceControllerMixin {
private static final String TAG = "MobileNetSummaryCtlr";
private static final String KEY = "mobile_network_list";
@@ -74,8 +76,10 @@
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mTelephonyMgr = mContext.getSystemService(TelephonyManager.class);
mEuiccManager = mContext.getSystemService(EuiccManager.class);
- mChangeListener = new SubscriptionsChangeListener(context, this);
- lifecycle.addObserver(this);
+ if (lifecycle != null) {
+ mChangeListener = new SubscriptionsChangeListener(context, this);
+ lifecycle.addObserver(this);
+ }
}
@OnLifecycleEvent(ON_RESUME)
@@ -116,6 +120,7 @@
private void startAddSimFlow() {
final Intent intent = new Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
+ intent.putExtra(EuiccManager.EXTRA_FORCE_PROVISION, true);
mContext.startActivity(intent);
}
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
index d120062..8d40175 100644
--- a/src/com/android/settings/print/PrintServiceSettingsFragment.java
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -143,6 +143,8 @@
@Override
public void onStart() {
super.onStart();
+ initComponents();
+ updateUiForArguments();
updateEmptyView();
updateUiForServiceState();
}
@@ -158,20 +160,9 @@
@Override
public void onStop() {
super.onStop();
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- initComponents();
- updateUiForArguments();
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
mSwitchBar.removeOnSwitchChangeListener(this);
mSwitchBar.hide();
+ mPrintersAdapter.unregisterAdapterDataObserver(mDataObserver);
}
private void onPreferenceToggled(String preferenceKey, boolean enabled) {
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index de2755e..07e957d 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -18,6 +18,8 @@
import android.content.Context;
import android.content.DialogInterface;
+import android.net.Proxy;
+import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.SystemProperties;
import android.security.Credentials;
@@ -67,6 +69,9 @@
private TextView mSearchDomains;
private TextView mDnsServers;
private TextView mRoutes;
+ private Spinner mProxySettings;
+ private TextView mProxyHost;
+ private TextView mProxyPort;
private CheckBox mMppe;
private TextView mL2tpSecret;
private TextView mIpsecIdentifier;
@@ -105,6 +110,9 @@
mSearchDomains = (TextView) mView.findViewById(R.id.search_domains);
mDnsServers = (TextView) mView.findViewById(R.id.dns_servers);
mRoutes = (TextView) mView.findViewById(R.id.routes);
+ mProxySettings = (Spinner) mView.findViewById(R.id.vpn_proxy_settings);
+ mProxyHost = (TextView) mView.findViewById(R.id.vpn_proxy_host);
+ mProxyPort = (TextView) mView.findViewById(R.id.vpn_proxy_port);
mMppe = (CheckBox) mView.findViewById(R.id.mppe);
mL2tpSecret = (TextView) mView.findViewById(R.id.l2tp_secret);
mIpsecIdentifier = (TextView) mView.findViewById(R.id.ipsec_identifier);
@@ -128,6 +136,11 @@
mSearchDomains.setText(mProfile.searchDomains);
mDnsServers.setText(mProfile.dnsServers);
mRoutes.setText(mProfile.routes);
+ if (mProfile.proxy != null) {
+ mProxyHost.setText(mProfile.proxy.getHost());
+ int port = mProfile.proxy.getPort();
+ mProxyPort.setText(port == 0 ? "" : Integer.toString(port));
+ }
mMppe.setChecked(mProfile.mppe);
mL2tpSecret.setText(mProfile.l2tpSecret);
mIpsecIdentifier.setText(mProfile.ipsecIdentifier);
@@ -153,6 +166,9 @@
mPassword.addTextChangedListener(this);
mDnsServers.addTextChangedListener(this);
mRoutes.addTextChangedListener(this);
+ mProxySettings.setOnItemSelectedListener(this);
+ mProxyHost.addTextChangedListener(this);
+ mProxyPort.addTextChangedListener(this);
mIpsecSecret.addTextChangedListener(this);
mIpsecUserCert.setOnItemSelectedListener(this);
mShowOptions.setOnClickListener(this);
@@ -175,7 +191,8 @@
// Switch to advanced view immediately if any advanced options are on
if (!mProfile.searchDomains.isEmpty() || !mProfile.dnsServers.isEmpty() ||
- !mProfile.routes.isEmpty()) {
+ !mProfile.routes.isEmpty() || (mProfile.proxy != null &&
+ (!mProfile.proxy.getHost().isEmpty() || mProfile.proxy.getPort() != 0))) {
showAdvancedOptions();
}
@@ -246,6 +263,8 @@
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent == mType) {
changeType(position);
+ } else if (parent == mProxySettings) {
+ updateProxyFieldsVisibility(position);
}
updateUiControls();
}
@@ -271,6 +290,7 @@
* These include:
* "Always-on VPN" checkbox
* Reason for "Always-on VPN" being disabled, when necessary
+ * Proxy info if manually configured
* "Save account information" checkbox
* "Save" and "Connect" buttons
*/
@@ -298,6 +318,13 @@
mAlwaysOnInvalidReason.setVisibility(View.VISIBLE);
}
+ // Show proxy fields if any proxy field is filled.
+ if (mProfile.proxy != null && (!mProfile.proxy.getHost().isEmpty() ||
+ mProfile.proxy.getPort() != 0)) {
+ mProxySettings.setSelection(VpnProfile.PROXY_MANUAL);
+ updateProxyFieldsVisibility(VpnProfile.PROXY_MANUAL);
+ }
+
// Save account information
if (mAlwaysOnVpn.isChecked()) {
mSaveLogin.setChecked(true);
@@ -311,6 +338,11 @@
getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(validate(mEditing));
}
+ private void updateProxyFieldsVisibility(int position) {
+ final int visible = position == VpnProfile.PROXY_MANUAL ? View.VISIBLE : View.GONE;
+ mView.findViewById(R.id.vpn_proxy_fields).setVisibility(visible);
+ }
+
private void showAdvancedOptions() {
mView.findViewById(R.id.options).setVisibility(View.VISIBLE);
mShowOptions.setVisibility(View.GONE);
@@ -361,6 +393,11 @@
!validateAddresses(mRoutes.getText().toString(), true)) {
return false;
}
+
+ if (!validateProxy()) {
+ return false;
+ }
+
switch (mType.getSelectedItemPosition()) {
case VpnProfile.TYPE_PPTP:
case VpnProfile.TYPE_IPSEC_HYBRID_RSA:
@@ -435,6 +472,10 @@
return mEditing;
}
+ boolean hasProxy() {
+ return mProxySettings.getSelectedItemPosition() == VpnProfile.PROXY_MANUAL;
+ }
+
VpnProfile getProfile() {
// First, save common fields.
VpnProfile profile = new VpnProfile(mProfile.key);
@@ -446,7 +487,16 @@
profile.searchDomains = mSearchDomains.getText().toString().trim();
profile.dnsServers = mDnsServers.getText().toString().trim();
profile.routes = mRoutes.getText().toString().trim();
-
+ if (hasProxy()) {
+ String proxyHost = mProxyHost.getText().toString().trim();
+ String proxyPort = mProxyPort.getText().toString().trim();
+ // 0 is a last resort default, but the interface validates that the proxy port is
+ // present and non-zero.
+ int port = proxyPort.isEmpty() ? 0 : Integer.parseInt(proxyPort);
+ profile.proxy = new ProxyInfo(proxyHost, port, null);
+ } else {
+ profile.proxy = null;
+ }
// Then, save type-specific fields.
switch (profile.type) {
case VpnProfile.TYPE_PPTP:
@@ -483,4 +533,15 @@
profile.saveLogin = mSaveLogin.isChecked() || (mEditing && hasLogin);
return profile;
}
+
+ private boolean validateProxy() {
+ if (!hasProxy()) {
+ return true;
+ }
+
+ final String host = mProxyHost.getText().toString().trim();
+ final String port = mProxyPort.getText().toString().trim();
+ return Proxy.validate(host, port, "") == Proxy.PROXY_VALID;
+ }
+
}
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index e7db5db..916d330 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -248,8 +248,8 @@
mMeteredSettingsSpinner = mView.findViewById(R.id.metered_settings);
mHiddenSettingsSpinner = mView.findViewById(R.id.hidden_settings);
mPrivacySettingsSpinner = mView.findViewById(R.id.privacy_settings);
- if (FeatureFlagUtils.isEnabled(mContext,
- com.android.settings.core.FeatureFlags.WIFI_MAC_RANDOMIZATION)) {
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_wifi_p2p_mac_randomization_supported)) {
View privacySettingsLayout = mView.findViewById(R.id.privacy_settings_fields);
privacySettingsLayout.setVisibility(View.VISIBLE);
}
diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
index b79f2d4..97ddc53 100644
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -58,8 +58,9 @@
@Override
public int getAvailabilityStatus() {
- return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.WIFI_MAC_RANDOMIZATION)
- ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_wifi_p2p_mac_randomization_supported) ?
+ AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
diff --git a/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java
new file mode 100644
index 0000000..ba7bd2c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarPreferenceTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.preference.PreferenceViewHolder;
+
+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 BalanceSeekBarPreferenceTest {
+ private static final int BALANCE_CENTER_VALUE = 100;
+ private static final int BALANCE_MAX_VALUE = 200;
+
+ private Context mContext;
+ private AttributeSet mAttrs;
+ private PreferenceViewHolder mHolder;
+ private BalanceSeekBar mSeekBar;
+ private BalanceSeekBarPreference mSeekBarPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mSeekBarPreference = new BalanceSeekBarPreference(mContext, mAttrs);
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ final View view =
+ inflater.inflate(mSeekBarPreference.getLayoutResource(),
+ new LinearLayout(mContext), false);
+ mHolder = PreferenceViewHolder.createInstanceForTests(view);
+ mSeekBar = (BalanceSeekBar) view.findViewById(com.android.internal.R.id.seekbar);
+ }
+
+ @Test
+ public void seekBarPreferenceOnBindViewHolder_shouldInitSeekBarValue() {
+ mSeekBarPreference.onBindViewHolder(mHolder);
+
+ assertThat(mSeekBar.getMax()).isEqualTo(BALANCE_MAX_VALUE);
+ assertThat(mSeekBar.getProgress()).isEqualTo(BALANCE_CENTER_VALUE);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java
new file mode 100644
index 0000000..e0dc681
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/BalanceSeekBarTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+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 BalanceSeekBarTest {
+ // Fix the maximum process value to 200 for testing the BalanceSeekBar.
+ // It affects the SeekBar value of center(100) and snapThreshold(200 * SNAP_TO_PERCENTAGE).
+ private static final int MAX_PROGRESS_VALUE = 200;
+
+ private Context mContext;
+ private AttributeSet mAttrs;
+ private BalanceSeekBar mSeekBar;
+ private BalanceSeekBar.OnSeekBarChangeListener mProxySeekBarListener;
+ private SeekBar.OnSeekBarChangeListener mockSeekBarChangeListener;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mSeekBar = new BalanceSeekBar(mContext, mAttrs);
+ mProxySeekBarListener = mSeekBar.getProxySeekBarListener();
+ mockSeekBarChangeListener = mock(SeekBar.OnSeekBarChangeListener.class);
+ mSeekBar.setOnSeekBarChangeListener(mockSeekBarChangeListener);
+ }
+
+ @Test
+ public void onStartTrackingTouch_shouldInvokeMethod() {
+ mProxySeekBarListener.onStartTrackingTouch(mSeekBar);
+
+ verify(mockSeekBarChangeListener, times(1)).onStartTrackingTouch(mSeekBar);
+ }
+
+ @Test
+ public void onStopTrackingTouch_shouldInvokeMethod() {
+ mProxySeekBarListener.onStopTrackingTouch(mSeekBar);
+
+ verify(mockSeekBarChangeListener, times(1)).onStopTrackingTouch(mSeekBar);
+ }
+
+ @Test
+ public void onProgressChanged_shouldInvokeMethod() {
+ // Assign the test value of SeekBar progress
+ mProxySeekBarListener.onProgressChanged(mSeekBar, MAX_PROGRESS_VALUE, true);
+
+ verify(mockSeekBarChangeListener, times(1)).onProgressChanged(eq(mSeekBar),
+ eq(MAX_PROGRESS_VALUE), eq(true));
+ }
+
+ @Test
+ public void setMaxTest_shouldSetValue() {
+ mSeekBar.setMax(MAX_PROGRESS_VALUE);
+
+ assertThat(getBalanceSeekBarCenter(mSeekBar)).isEqualTo(MAX_PROGRESS_VALUE / 2);
+ assertThat(getBalanceSeekBarSnapThreshold(mSeekBar)).isEqualTo(
+ MAX_PROGRESS_VALUE * BalanceSeekBar.SNAP_TO_PERCENTAGE);
+ }
+
+ @Test
+ public void setProgressTest_shouldSnapToCenter() {
+ // Assign the test value of SeekBar progress within the threshold (94-106 in this case).
+ final int progressWithinThreshold = 102;
+ mSeekBar.setMax(MAX_PROGRESS_VALUE);
+ mSeekBar.setProgress(progressWithinThreshold + 10); //set progress which is over threshold.
+ mProxySeekBarListener.onProgressChanged(mSeekBar, progressWithinThreshold, true);
+
+ assertThat(mSeekBar.getProgress()).isEqualTo(getBalanceSeekBarCenter(mSeekBar));
+ }
+
+ @Test
+ public void setProgressTest_shouldMaintainInputValue() {
+ // Assign the test value of SeekBar progress without the threshold.
+ final int progressWithoutThreshold = 107;
+ mSeekBar.setMax(MAX_PROGRESS_VALUE);
+ mSeekBar.setProgress(progressWithoutThreshold);
+ mProxySeekBarListener.onProgressChanged(mSeekBar, progressWithoutThreshold, true);
+
+ assertThat(mSeekBar.getProgress()).isEqualTo(progressWithoutThreshold);
+ }
+
+ // method to get the center from BalanceSeekBar for testing setMax().
+ private int getBalanceSeekBarCenter(BalanceSeekBar seekBar) {
+ return seekBar.getMax() / 2;
+ }
+
+ // method to get the snapThreshold from BalanceSeekBar for testing setMax().
+ private float getBalanceSeekBarSnapThreshold(BalanceSeekBar seekBar) {
+ return seekBar.getMax() * BalanceSeekBar.SNAP_TO_PERCENTAGE;
+ }
+}