Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9a5ceb8a authored by Nikhil Nayunigari's avatar Nikhil Nayunigari
Browse files

Add proxy settings to the ethernet dialog

Adds proxy settings and custom interface name to the ethernet dialog.

Flag: com.android.settings.connectivity.ethernet_settings

Test: Manual testing on a Pixel tablet
Change-Id: I5f2238fd94a4e17049934cac08b329d5c44f0018
parent d3b0498f
Loading
Loading
Loading
Loading
+183 −2
Original line number Diff line number Diff line
@@ -22,18 +22,199 @@
        android:scrollIndicators="top|bottom">

    <LinearLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:theme="@style/Theme.Network"
        android:id="@+id/l_ethernetdialog"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingBottom="8dip">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="16dp">

            <TextView
                android:id="@+id/ethernet_name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/ethernet_item_label"
                android:text="Port name"
                android:textSize="16sp"
                android:textColor="@android:color/holo_blue_dark"
                android:layout_marginBottom="8dp" />

            <EditText
                android:id="@+id/ethernet_name_edit_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/ethernet_item_edit_content"
                android:background="@null"
                android:hint="Ethernet"
                android:inputType="text"
                android:paddingBottom="8dp"
                android:textColor="@android:color/black"
                android:textSize="16sp"
                android:maxLines="1"
                android:minLines="1"/>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:background="@android:color/darker_gray" />

        </LinearLayout>

        <LinearLayout android:id="@+id/wifi_advanced_toggle"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      style="@style/wifi_item"
                      android:paddingTop="2dp"
                      android:paddingBottom="4dp"
                      android:importantForAccessibility="no"
                      android:visibility="visible">
            <CheckBox android:id="@+id/wifi_advanced_togglebox"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      style="@style/wifi_advanced_toggle"
                      android:importantForAccessibility="yes"
                      android:contentDescription="@string/wifi_advanced_toggle_description"
                      android:text="@string/wifi_show_advanced"/>
        </LinearLayout>

        <LinearLayout android:id="@+id/ethernet_advanced_fields"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:orientation="vertical"
                      android:visibility="gone">

            <LinearLayout android:id="@+id/proxy_settings_fields"
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          style="@style/wifi_item"
                          android:visibility="visible">

                <TextView android:id="@+id/proxy_settings_title"
                          android:layout_width="wrap_content"
                          android:layout_height="wrap_content"
                          style="@style/wifi_item_label"
                          android:text="@string/proxy_settings_title"/>

                <Spinner android:id="@+id/proxy_settings"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
                         style="@style/wifi_item_spinner"
                         android:prompt="@string/proxy_settings_title"
                         android:entries="@array/wifi_proxy_settings"/>

            </LinearLayout>

            <LinearLayout android:id="@+id/proxy_warning_limited_support"
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          style="@style/wifi_item"
                          android:visibility="gone">
                <!--  Placeholder to enable right-justification of warning -->
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    style="@style/wifi_item_label"/>

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    style="@style/wifi_item_content"
                    android:text="@string/proxy_warning_limited_support"/>
            </LinearLayout>

            <LinearLayout android:id="@+id/proxy_pac_field"
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          style="@style/wifi_section"
                          android:visibility="gone">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    style="@style/wifi_item">
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/wifi_item_label"
                        android:text="@string/proxy_url_title"/>

                    <EditText android:id="@+id/proxy_pac"
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              style="@style/wifi_item_edit_content"
                              android:hint="@string/proxy_url_hint"
                              android:inputType="textNoSuggestions"
                              android:singleLine="true"/>
                </LinearLayout>
            </LinearLayout>
            <LinearLayout android:id="@+id/proxy_fields"
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
                          style="@style/wifi_section"
                          android:visibility="gone">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    style="@style/wifi_item">
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/wifi_item_label"
                        android:text="@string/proxy_hostname_label"/>

                    <EditText android:id="@+id/proxy_hostname"
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              style="@style/wifi_item_edit_content"
                              android:hint="@string/proxy_hostname_hint"
                              android:inputType="textNoSuggestions"
                              android:singleLine="true"/>
                </LinearLayout>
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    style="@style/wifi_item">
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/wifi_item_label"
                        android:text="@string/proxy_port_label"/>

                    <EditText android:id="@+id/proxy_port"
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              style="@style/wifi_item_edit_content"
                              android:hint="@string/proxy_port_hint"
                              android:inputType="number"
                              android:singleLine="true"/>
                </LinearLayout>
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    style="@style/wifi_item">
                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        style="@style/wifi_item_label"
                        android:text="@string/proxy_exclusionlist_label"/>

                    <EditText android:id="@+id/proxy_exclusionlist"
                              android:layout_width="match_parent"
                              android:layout_height="wrap_content"
                              style="@style/wifi_item_edit_content"
                              android:hint="@string/proxy_exclusionlist_hint"
                              android:inputType="textNoSuggestions"
                              android:singleLine="true"/>
                </LinearLayout>
            </LinearLayout>

            <LinearLayout android:id="@+id/ip_fields"
                          android:layout_width="match_parent"
                          android:layout_height="wrap_content"
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
    xmlns:settings="http://schemas.android.com/apk/res-auto">

    <com.android.settingslib.widget.LayoutPreference
        android:key="connection_header"
        android:key="ethernet_details"
        android:layout="@layout/settings_entity_header"
        android:selectable="false"
        android:order="-10000"/>
+2 −0
Original line number Diff line number Diff line
@@ -20,4 +20,6 @@ import android.net.IpConfiguration

interface EthernetDialogController {
    fun getConfig(): IpConfiguration

    fun getInterfaceName(): String
}
+191 −29
Original line number Diff line number Diff line
@@ -17,18 +17,27 @@
package com.android.settings.network.ethernet

import android.content.Context
import android.content.SharedPreferences
import android.net.InetAddresses
import android.net.IpConfiguration
import android.net.IpConfiguration.IpAssignment
import android.net.IpConfiguration.ProxySettings
import android.net.LinkAddress
import android.net.ProxyInfo
import android.net.StaticIpConfiguration
import android.net.Uri
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.view.View
import android.widget.AdapterView
import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.CompoundButton.OnCheckedChangeListener
import android.widget.Spinner
import android.widget.TextView
import com.android.net.module.util.NetUtils
import com.android.net.module.util.ProxyUtils
import com.android.settings.ProxySelector
import com.android.settings.R
import java.net.Inet4Address
import java.net.InetAddress
@@ -38,42 +47,58 @@ class EthernetDialogControllerImpl(
    private val ipConfiguration: IpConfiguration,
    private val parentView: View,
    private val dialog: EthernetDialog,
) : AdapterView.OnItemSelectedListener, EthernetDialogController {
    private val preferenceId: String,
) : AdapterView.OnItemSelectedListener, EthernetDialogController, OnCheckedChangeListener {

    private val DHCP = 0
    private val STATIC_IP = 1

    private val PROXY_NONE = 0
    private val PROXY_MANUAL = 1
    private val PROXY_AUTO_CONFIG = 2

    private lateinit var mIpSettingsSpinner: Spinner

    private lateinit var mProxySettingsSpinner: Spinner

    private lateinit var mIpAddressView: TextView
    private lateinit var mGatewayView: TextView
    private lateinit var mNetworkPrefixLengthView: TextView
    private lateinit var mDns1View: TextView
    private lateinit var mDns2View: TextView

    private var mStaticIpConfiguration = StaticIpConfiguration()
    private lateinit var mInterfaceNameView: TextView

    private lateinit var mProxyPacView: TextView
    private lateinit var mProxyHostView: TextView
    private lateinit var mProxyPortView: TextView
    private lateinit var mProxyExclusionListView: TextView

    private var mIpAssignment: IpAssignment = IpAssignment.UNASSIGNED
    private var mProxySettings: ProxySettings = ProxySettings.UNASSIGNED
    private var mHttpProxy: ProxyInfo? = null
    private var mStaticIpConfiguration: StaticIpConfiguration? = null
    private var mEthernetInterfaceName = ""

    private val sharedPreferences: SharedPreferences =
        context.getSharedPreferences("ethernet_preferences", Context.MODE_PRIVATE)

    init {
        initEthernetDialog()
    }

    private fun initEthernetDialog() {
        mIpSettingsSpinner = parentView.findViewById(R.id.ip_settings)
        mIpSettingsSpinner.setOnItemSelectedListener(this)
        var showAdvancedFields = false

        mIpAddressView = parentView.findViewById<TextView>(R.id.ipaddress)
        mIpAddressView.addTextChangedListener(getIpConfigFieldsTextWatcher(mIpAddressView))
        mGatewayView = parentView.findViewById<TextView>(R.id.gateway)
        mGatewayView.addTextChangedListener(getIpConfigFieldsTextWatcher(mGatewayView))
        mNetworkPrefixLengthView = parentView.findViewById<TextView>(R.id.network_prefix_length)
        mNetworkPrefixLengthView.addTextChangedListener(
            getIpConfigFieldsTextWatcher(mNetworkPrefixLengthView)
        )
        mDns1View = parentView.findViewById<TextView>(R.id.dns1)
        mDns1View.addTextChangedListener(getIpConfigFieldsTextWatcher(mDns1View))
        mDns2View = parentView.findViewById<TextView>(R.id.dns2)
        mDns2View.addTextChangedListener(getIpConfigFieldsTextWatcher(mDns2View))
        initializeReferences()

        val interfaceName: String? = sharedPreferences.getString(preferenceId, null)
        if (interfaceName != null) {
            mInterfaceNameView.setText(interfaceName)
        }

        if (ipConfiguration.getIpAssignment() == IpConfiguration.IpAssignment.STATIC) {
        if (ipConfiguration.getIpAssignment() == IpAssignment.STATIC) {
            showAdvancedFields = true
            mIpSettingsSpinner.setSelection(STATIC_IP)

            val staticIp = ipConfiguration.getStaticIpConfiguration()
@@ -96,20 +121,119 @@ class EthernetDialogControllerImpl(
        } else {
            mIpSettingsSpinner.setSelection(DHCP)
        }

        if (ipConfiguration.getProxySettings() == ProxySettings.STATIC) {
            showAdvancedFields = true
            mProxySettingsSpinner.setSelection(PROXY_MANUAL)
            val proxyProperties: ProxyInfo? = ipConfiguration.getHttpProxy()
            if (proxyProperties != null) {
                mProxyHostView.setText(proxyProperties.getHost())
                mProxyPortView.setText(Integer.toString(proxyProperties.getPort()))
                mProxyExclusionListView.setText(
                    ProxyUtils.exclusionListAsString(proxyProperties.getExclusionList())
                )
            }
        } else if (ipConfiguration.getProxySettings() == ProxySettings.PAC) {
            showAdvancedFields = true
            mProxySettingsSpinner.setSelection(PROXY_AUTO_CONFIG)
            val proxyInfo: ProxyInfo? = ipConfiguration.getHttpProxy()
            mProxyPacView?.setText(proxyInfo?.getPacFileUrl()?.toString())
        } else {
            mProxySettingsSpinner.setSelection(PROXY_NONE)
        }

        val advancedTogglebox: CheckBox =
            parentView.findViewById<CheckBox>(R.id.wifi_advanced_togglebox)
        if (!showAdvancedFields) {
            parentView.findViewById<View>(R.id.wifi_advanced_toggle).setVisibility(View.VISIBLE)
            advancedTogglebox.setOnCheckedChangeListener(this)
            advancedTogglebox.setChecked(showAdvancedFields)
        }
        parentView.findViewById<View>(R.id.ethernet_advanced_fields).visibility =
            if (showAdvancedFields) View.VISIBLE else View.GONE
    }

    private fun initializeReferences() {
        mIpSettingsSpinner = parentView.findViewById(R.id.ip_settings)
        mIpSettingsSpinner.setOnItemSelectedListener(this)

        mProxySettingsSpinner = parentView.findViewById(R.id.proxy_settings)
        mProxySettingsSpinner.setOnItemSelectedListener(this)

        mInterfaceNameView = parentView.findViewById<TextView>(R.id.ethernet_name_edit_text)
        mInterfaceNameView.addTextChangedListener(getTextFieldsWatcher(mInterfaceNameView))

        mIpAddressView = parentView.findViewById<TextView>(R.id.ipaddress)
        mIpAddressView.addTextChangedListener(getTextFieldsWatcher(mIpAddressView))

        mGatewayView = parentView.findViewById<TextView>(R.id.gateway)
        mGatewayView.addTextChangedListener(getTextFieldsWatcher(mGatewayView))

        mNetworkPrefixLengthView = parentView.findViewById<TextView>(R.id.network_prefix_length)
        mNetworkPrefixLengthView.addTextChangedListener(
            getTextFieldsWatcher(mNetworkPrefixLengthView)
        )

        mDns1View = parentView.findViewById<TextView>(R.id.dns1)
        mDns1View.addTextChangedListener(getTextFieldsWatcher(mDns1View))
        mDns2View = parentView.findViewById<TextView>(R.id.dns2)
        mDns2View.addTextChangedListener(getTextFieldsWatcher(mDns2View))

        mProxyPacView = parentView.findViewById<TextView>(R.id.proxy_pac)
        mProxyPacView?.addTextChangedListener(getTextFieldsWatcher(mProxyPacView))

        mProxyHostView = parentView.findViewById<TextView>(R.id.proxy_hostname)
        mProxyHostView.addTextChangedListener(getTextFieldsWatcher(mProxyHostView))

        mProxyPortView = parentView.findViewById<TextView>(R.id.proxy_port)
        mProxyPortView.addTextChangedListener(getTextFieldsWatcher(mProxyPortView))

        mProxyExclusionListView = parentView.findViewById<TextView>(R.id.proxy_exclusionlist)
        mProxyExclusionListView.addTextChangedListener(
            getTextFieldsWatcher(mProxyExclusionListView)
        )
    }

    override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        parentView.findViewById<View>(R.id.ip_fields)?.setVisibility(View.VISIBLE)
        if (mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) {
            parentView.findViewById<View>(R.id.staticip)?.setVisibility(View.VISIBLE)
            ipConfiguration.setIpAssignment(IpConfiguration.IpAssignment.STATIC)
            setVisibility(R.id.staticip, View.VISIBLE)
            mIpAssignment = IpAssignment.STATIC
        } else {
            setVisibility(R.id.staticip, View.GONE)
            mIpAssignment = IpAssignment.DHCP
        }

        if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_MANUAL) {
            setVisibility(R.id.proxy_warning_limited_support, View.VISIBLE)
            setVisibility(R.id.proxy_fields, View.VISIBLE)
            setVisibility(R.id.proxy_pac_field, View.GONE)
            mProxySettings = ProxySettings.STATIC
        } else if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_AUTO_CONFIG) {
            setVisibility(R.id.proxy_warning_limited_support, View.GONE)
            setVisibility(R.id.proxy_fields, View.GONE)
            setVisibility(R.id.proxy_pac_field, View.VISIBLE)
            mProxySettings = ProxySettings.PAC
        } else {
            parentView.findViewById<View>(R.id.staticip)?.setVisibility(View.GONE)
            ipConfiguration.setIpAssignment(IpConfiguration.IpAssignment.DHCP)
            setVisibility(R.id.proxy_warning_limited_support, View.GONE)
            setVisibility(R.id.proxy_fields, View.GONE)
            setVisibility(R.id.proxy_pac_field, View.GONE)
            mProxySettings = ProxySettings.NONE
        }
    }

    private fun getIpConfigFieldsTextWatcher(view: TextView): TextWatcher {
    private fun setVisibility(id: Int, visibility: Int) {
        val v: View? = parentView.findViewById(id)
        v?.setVisibility(visibility)
    }

    override fun onCheckedChanged(view: CompoundButton, isChecked: Boolean) {
        if (view.getId() == R.id.wifi_advanced_togglebox) {
            view.setVisibility(View.GONE)
            parentView.findViewById<View>(R.id.ethernet_advanced_fields).setVisibility(View.VISIBLE)
        }
    }

    fun getTextFieldsWatcher(view: TextView): TextWatcher {
        return object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
                // work done in afterTextChanged
@@ -120,8 +244,41 @@ class EthernetDialogControllerImpl(
            }

            override fun afterTextChanged(s: Editable) {
                captureProxySettings()
                captureIpConfiguration()
                captureInterfaceName()
            }
        }
    }

    private fun captureInterfaceName() {
        mEthernetInterfaceName = mInterfaceNameView.text.toString()
    }

    private fun captureProxySettings() {
        val selectedPosition = mProxySettingsSpinner.getSelectedItemPosition()
        if (selectedPosition == PROXY_MANUAL) {
            val host = mProxyHostView.text.toString()
            val portStr = mProxyPortView.text.toString()
            val exclusionList = mProxyExclusionListView.text.toString()
            var port = 0
            try {
                port = Integer.parseInt(portStr)
                if (
                    ProxySelector.validate(host, portStr, exclusionList) == ProxyUtils.PROXY_VALID
                ) {
                    mHttpProxy = ProxyInfo.buildDirectProxy(host, port, exclusionList.split(","))
                }
            } catch (e: NumberFormatException) {
                return
            }
        } else if (selectedPosition == PROXY_AUTO_CONFIG) {
            val uriSequence: CharSequence = mProxyPacView.text
            if (uriSequence.isNullOrEmpty()) {
                return
            }
            val uri: Uri = Uri.parse(uriSequence.toString()) ?: return
            mHttpProxy = ProxyInfo.buildPacProxy(uri)
        }
    }

@@ -130,8 +287,8 @@ class EthernetDialogControllerImpl(
            val ipAddr = mIpAddressView.text.toString()
            if (ipAddr.isEmpty()) return

            val inetAddr = getIPv4Address(ipAddr)
            if (inetAddr == null || inetAddr == Inet4Address.ANY) {
            val inetAddr: Inet4Address? = getIPv4Address(ipAddr)
            if (inetAddr == null || inetAddr.toString().equals("0.0.0.0")) {
                return
            }

@@ -154,7 +311,7 @@ class EthernetDialogControllerImpl(
                }

                val gateway = mGatewayView.text.toString()
                if (TextUtils.isEmpty(gateway)) {
                if (gateway.isNullOrEmpty()) {
                    try {
                        val netPart = NetUtils.getNetworkPart(inetAddr, networkPrefixLength)
                        val addr = netPart.address
@@ -173,7 +330,7 @@ class EthernetDialogControllerImpl(
                var dnsAddr: InetAddress? = null
                val dnsServers = ArrayList<InetAddress>()

                if (TextUtils.isEmpty(dns)) {
                if (dns.isNullOrEmpty()) {
                    mDns1View.setText(context.getString(R.string.ethernet_dns1_hint))
                } else {
                    dnsAddr = getIPv4Address(dns)
@@ -183,7 +340,7 @@ class EthernetDialogControllerImpl(
                    dnsServers.add(dnsAddr)
                }

                if (mDns2View.length() > 0) {
                if (!mDns2View.text.toString().isNullOrEmpty()) {
                    dns = mDns2View.text.toString()
                    dnsAddr = getIPv4Address(dns)
                    if (dnsAddr == null) {
@@ -215,6 +372,11 @@ class EthernetDialogControllerImpl(

    override fun getConfig(): IpConfiguration {
        ipConfiguration.setStaticIpConfiguration(mStaticIpConfiguration)
        ipConfiguration.setIpAssignment(mIpAssignment)
        ipConfiguration.setProxySettings(mProxySettings)
        ipConfiguration.setHttpProxy(mHttpProxy)
        return ipConfiguration
    }

    override fun getInterfaceName() = mEthernetInterfaceName
}
+3 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ class EthernetDialogImpl(
    context: Context,
    private val listener: EthernetDialogListener,
    private val ipConfiguration: IpConfiguration,
    private val preferenceId: String,
    @StyleRes style: Int = 0,
) : AlertDialog(context, style), DialogInterface.OnClickListener, EthernetDialog {

@@ -51,7 +52,8 @@ class EthernetDialogImpl(
        setSubmitButton(context.getString(R.string.ethernet_config_submit))
        setCancelButton(context.getString(R.string.ethernet_config_cancel))
        setTitle(context.getString(R.string.ethernet_config_title))
        controller = EthernetDialogControllerImpl(context, ipConfiguration, view, this)
        controller =
            EthernetDialogControllerImpl(context, ipConfiguration, view, this, preferenceId)
        super.onCreate(savedInstanceState)
    }

Loading