| /* | |
| * Copyright (C) 2006 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; | |
| import android.app.Activity; | |
| import android.app.Dialog; | |
| import android.app.admin.DevicePolicyManager; | |
| import android.app.settings.SettingsEnums; | |
| import android.content.Context; | |
| import android.content.Intent; | |
| import android.net.ConnectivityManager; | |
| import android.net.ProxyInfo; | |
| import android.os.Bundle; | |
| import android.text.Selection; | |
| import android.text.Spannable; | |
| import android.text.TextUtils; | |
| import android.util.Log; | |
| import android.view.LayoutInflater; | |
| import android.view.View; | |
| import android.view.View.OnClickListener; | |
| import android.view.View.OnFocusChangeListener; | |
| import android.view.ViewGroup; | |
| import android.widget.Button; | |
| import android.widget.EditText; | |
| import android.widget.TextView; | |
| import androidx.appcompat.app.AlertDialog; | |
| import com.android.net.module.util.ProxyUtils; | |
| import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment; | |
| import com.android.settings.core.InstrumentedFragment; | |
| import java.util.Arrays; | |
| public class ProxySelector extends InstrumentedFragment implements DialogCreatable { | |
| private static final String TAG = "ProxySelector"; | |
| EditText mHostnameField; | |
| EditText mPortField; | |
| EditText mExclusionListField; | |
| Button mOKButton; | |
| Button mClearButton; | |
| Button mDefaultButton; | |
| private static final int ERROR_DIALOG_ID = 0; | |
| private SettingsDialogFragment mDialogFragment; | |
| private View mView; | |
| @Override | |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, | |
| Bundle savedInstanceState) { | |
| mView = inflater.inflate(R.layout.proxy, container, false); | |
| initView(mView); | |
| // TODO: Populate based on connection status | |
| populateFields(); | |
| return mView; | |
| } | |
| @Override | |
| public void onActivityCreated(Bundle savedInstanceState) { | |
| super.onActivityCreated(savedInstanceState); | |
| final DevicePolicyManager dpm = | |
| (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE); | |
| final boolean userSetGlobalProxy = (dpm.getGlobalProxyAdmin() == null); | |
| // Disable UI if the Global Proxy is being controlled by a Device Admin | |
| mHostnameField.setEnabled(userSetGlobalProxy); | |
| mPortField.setEnabled(userSetGlobalProxy); | |
| mExclusionListField.setEnabled(userSetGlobalProxy); | |
| mOKButton.setEnabled(userSetGlobalProxy); | |
| mClearButton.setEnabled(userSetGlobalProxy); | |
| mDefaultButton.setEnabled(userSetGlobalProxy); | |
| } | |
| // Dialog management | |
| @Override | |
| public Dialog onCreateDialog(int id) { | |
| if (id == ERROR_DIALOG_ID) { | |
| String hostname = mHostnameField.getText().toString().trim(); | |
| String portStr = mPortField.getText().toString().trim(); | |
| String exclList = mExclusionListField.getText().toString().trim(); | |
| String msg = getActivity().getString(validate(hostname, portStr, exclList)); | |
| return new AlertDialog.Builder(getActivity()) | |
| .setTitle(R.string.proxy_error) | |
| .setPositiveButton(R.string.proxy_error_dismiss, null) | |
| .setMessage(msg) | |
| .create(); | |
| } | |
| return null; | |
| } | |
| @Override | |
| public int getDialogMetricsCategory(int dialogId) { | |
| return SettingsEnums.DIALOG_PROXY_SELECTOR_ERROR; | |
| } | |
| private void showDialog(int dialogId) { | |
| if (mDialogFragment != null) { | |
| Log.e(TAG, "Old dialog fragment not null!"); | |
| } | |
| mDialogFragment = SettingsDialogFragment.newInstance(this, dialogId); | |
| mDialogFragment.show(getActivity().getSupportFragmentManager(), Integer.toString(dialogId)); | |
| } | |
| private void initView(View view) { | |
| mHostnameField = (EditText)view.findViewById(R.id.hostname); | |
| mHostnameField.setOnFocusChangeListener(mOnFocusChangeHandler); | |
| mPortField = (EditText)view.findViewById(R.id.port); | |
| mPortField.setOnClickListener(mOKHandler); | |
| mPortField.setOnFocusChangeListener(mOnFocusChangeHandler); | |
| mExclusionListField = (EditText)view.findViewById(R.id.exclusionlist); | |
| mExclusionListField.setOnFocusChangeListener(mOnFocusChangeHandler); | |
| mOKButton = (Button)view.findViewById(R.id.action); | |
| mOKButton.setOnClickListener(mOKHandler); | |
| mClearButton = (Button)view.findViewById(R.id.clear); | |
| mClearButton.setOnClickListener(mClearHandler); | |
| mDefaultButton = (Button)view.findViewById(R.id.defaultView); | |
| mDefaultButton.setOnClickListener(mDefaultHandler); | |
| } | |
| void populateFields() { | |
| final Activity activity = getActivity(); | |
| String hostname = ""; | |
| int port = -1; | |
| String exclList = ""; | |
| // Use the last setting given by the user | |
| ConnectivityManager cm = | |
| (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); | |
| ProxyInfo proxy = cm.getGlobalProxy(); | |
| if (proxy != null) { | |
| hostname = proxy.getHost(); | |
| port = proxy.getPort(); | |
| exclList = ProxyUtils.exclusionListAsString(proxy.getExclusionList()); | |
| } | |
| if (hostname == null) { | |
| hostname = ""; | |
| } | |
| mHostnameField.setText(hostname); | |
| String portStr = port == -1 ? "" : Integer.toString(port); | |
| mPortField.setText(portStr); | |
| mExclusionListField.setText(exclList); | |
| final Intent intent = activity.getIntent(); | |
| String buttonLabel = intent.getStringExtra("button-label"); | |
| if (!TextUtils.isEmpty(buttonLabel)) { | |
| mOKButton.setText(buttonLabel); | |
| } | |
| String title = intent.getStringExtra("title"); | |
| if (!TextUtils.isEmpty(title)) { | |
| activity.setTitle(title); | |
| } else { | |
| activity.setTitle(R.string.proxy_settings_title); | |
| } | |
| } | |
| /** | |
| * validate syntax of hostname and port entries | |
| * @return 0 on success, string resource ID on failure | |
| */ | |
| public static int validate(String hostname, String port, String exclList) { | |
| switch (ProxyUtils.validate(hostname, port, exclList)) { | |
| case ProxyUtils.PROXY_VALID: | |
| return 0; | |
| case ProxyUtils.PROXY_HOSTNAME_EMPTY: | |
| return R.string.proxy_error_empty_host_set_port; | |
| case ProxyUtils.PROXY_HOSTNAME_INVALID: | |
| return R.string.proxy_error_invalid_host; | |
| case ProxyUtils.PROXY_PORT_EMPTY: | |
| return R.string.proxy_error_empty_port; | |
| case ProxyUtils.PROXY_PORT_INVALID: | |
| return R.string.proxy_error_invalid_port; | |
| case ProxyUtils.PROXY_EXCLLIST_INVALID: | |
| return R.string.proxy_error_invalid_exclusion_list; | |
| default: | |
| // should neven happen | |
| Log.e(TAG, "Unknown proxy settings error"); | |
| return -1; | |
| } | |
| } | |
| /** | |
| * returns true on success, false if the user must correct something | |
| */ | |
| boolean saveToDb() { | |
| String hostname = mHostnameField.getText().toString().trim(); | |
| String portStr = mPortField.getText().toString().trim(); | |
| String exclList = mExclusionListField.getText().toString().trim(); | |
| int port = 0; | |
| int result = validate(hostname, portStr, exclList); | |
| if (result != 0) { | |
| showDialog(ERROR_DIALOG_ID); | |
| return false; | |
| } | |
| if (portStr.length() > 0) { | |
| try { | |
| port = Integer.parseInt(portStr); | |
| } catch (NumberFormatException ex) { | |
| // should never happen - caught by validate above | |
| return false; | |
| } | |
| } | |
| ProxyInfo p = ProxyInfo.buildDirectProxy( | |
| hostname, port, Arrays.asList(exclList.split(","))); | |
| // FIXME: The best solution would be to make a better UI that would | |
| // disable editing of the text boxes if the user chooses to use the | |
| // default settings. i.e. checking a box to always use the default | |
| // carrier. http:/b/issue?id=756480 | |
| // FIXME: If the user types in a proxy that matches the default, should | |
| // we keep that setting? Can be fixed with a new UI. | |
| ConnectivityManager cm = | |
| (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); | |
| cm.setGlobalProxy(p); | |
| return true; | |
| } | |
| OnClickListener mOKHandler = new OnClickListener() { | |
| public void onClick(View v) { | |
| if (saveToDb()) { | |
| getActivity().onBackPressed(); | |
| } | |
| } | |
| }; | |
| OnClickListener mClearHandler = new OnClickListener() { | |
| public void onClick(View v) { | |
| mHostnameField.setText(""); | |
| mPortField.setText(""); | |
| mExclusionListField.setText(""); | |
| } | |
| }; | |
| OnClickListener mDefaultHandler = new OnClickListener() { | |
| public void onClick(View v) { | |
| // TODO: populate based on connection status | |
| populateFields(); | |
| } | |
| }; | |
| OnFocusChangeListener mOnFocusChangeHandler = new OnFocusChangeListener() { | |
| public void onFocusChange(View v, boolean hasFocus) { | |
| if (hasFocus) { | |
| TextView textView = (TextView) v; | |
| Selection.selectAll((Spannable) textView.getText()); | |
| } | |
| } | |
| }; | |
| @Override | |
| public int getMetricsCategory() { | |
| return SettingsEnums.PROXY_SELECTOR; | |
| } | |
| } |