2 * Copyright (C) 2006 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.settings;
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.app.Dialog;
22 import android.app.admin.DevicePolicyManager;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.net.ConnectivityManager;
26 import android.net.Proxy;
27 import android.net.ProxyInfo;
28 import android.os.Bundle;
29 import android.text.Selection;
30 import android.text.Spannable;
31 import android.text.TextUtils;
32 import android.util.Log;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.view.View.OnClickListener;
36 import android.view.View.OnFocusChangeListener;
37 import android.view.ViewGroup;
38 import android.widget.Button;
39 import android.widget.EditText;
40 import android.widget.TextView;
42 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
43 import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment;
44 import com.android.settings.core.InstrumentedFragment;
46 public class ProxySelector extends InstrumentedFragment implements DialogCreatable {
47 private static final String TAG = "ProxySelector";
49 EditText mHostnameField;
51 EditText mExclusionListField;
54 Button mDefaultButton;
56 private static final int ERROR_DIALOG_ID = 0;
58 private SettingsDialogFragment mDialogFragment;
62 public void onCreate(Bundle icicle) {
63 super.onCreate(icicle);
67 public View onCreateView(LayoutInflater inflater, ViewGroup container,
68 Bundle savedInstanceState) {
69 mView = inflater.inflate(R.layout.proxy, container, false);
71 // TODO: Populate based on connection status
77 public void onActivityCreated(Bundle savedInstanceState) {
78 super.onActivityCreated(savedInstanceState);
79 final DevicePolicyManager dpm =
80 (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
82 final boolean userSetGlobalProxy = (dpm.getGlobalProxyAdmin() == null);
83 // Disable UI if the Global Proxy is being controlled by a Device Admin
84 mHostnameField.setEnabled(userSetGlobalProxy);
85 mPortField.setEnabled(userSetGlobalProxy);
86 mExclusionListField.setEnabled(userSetGlobalProxy);
87 mOKButton.setEnabled(userSetGlobalProxy);
88 mClearButton.setEnabled(userSetGlobalProxy);
89 mDefaultButton.setEnabled(userSetGlobalProxy);
95 public Dialog onCreateDialog(int id) {
96 if (id == ERROR_DIALOG_ID) {
97 String hostname = mHostnameField.getText().toString().trim();
98 String portStr = mPortField.getText().toString().trim();
99 String exclList = mExclusionListField.getText().toString().trim();
100 String msg = getActivity().getString(validate(hostname, portStr, exclList));
102 return new AlertDialog.Builder(getActivity())
103 .setTitle(R.string.proxy_error)
104 .setPositiveButton(R.string.proxy_error_dismiss, null)
112 public int getDialogMetricsCategory(int dialogId) {
113 return MetricsEvent.DIALOG_PROXY_SELECTOR_ERROR;
116 private void showDialog(int dialogId) {
117 if (mDialogFragment != null) {
118 Log.e(TAG, "Old dialog fragment not null!");
120 mDialogFragment = new SettingsDialogFragment(this, dialogId);
121 mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
124 private void initView(View view) {
125 mHostnameField = (EditText)view.findViewById(R.id.hostname);
126 mHostnameField.setOnFocusChangeListener(mOnFocusChangeHandler);
128 mPortField = (EditText)view.findViewById(R.id.port);
129 mPortField.setOnClickListener(mOKHandler);
130 mPortField.setOnFocusChangeListener(mOnFocusChangeHandler);
132 mExclusionListField = (EditText)view.findViewById(R.id.exclusionlist);
133 mExclusionListField.setOnFocusChangeListener(mOnFocusChangeHandler);
135 mOKButton = (Button)view.findViewById(R.id.action);
136 mOKButton.setOnClickListener(mOKHandler);
138 mClearButton = (Button)view.findViewById(R.id.clear);
139 mClearButton.setOnClickListener(mClearHandler);
141 mDefaultButton = (Button)view.findViewById(R.id.defaultView);
142 mDefaultButton.setOnClickListener(mDefaultHandler);
145 void populateFields() {
146 final Activity activity = getActivity();
147 String hostname = "";
149 String exclList = "";
150 // Use the last setting given by the user
151 ConnectivityManager cm =
152 (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
154 ProxyInfo proxy = cm.getGlobalProxy();
156 hostname = proxy.getHost();
157 port = proxy.getPort();
158 exclList = proxy.getExclusionListAsString();
161 if (hostname == null) {
165 mHostnameField.setText(hostname);
167 String portStr = port == -1 ? "" : Integer.toString(port);
168 mPortField.setText(portStr);
170 mExclusionListField.setText(exclList);
172 final Intent intent = activity.getIntent();
174 String buttonLabel = intent.getStringExtra("button-label");
175 if (!TextUtils.isEmpty(buttonLabel)) {
176 mOKButton.setText(buttonLabel);
179 String title = intent.getStringExtra("title");
180 if (!TextUtils.isEmpty(title)) {
181 activity.setTitle(title);
186 * validate syntax of hostname and port entries
187 * @return 0 on success, string resource ID on failure
189 public static int validate(String hostname, String port, String exclList) {
190 switch (Proxy.validate(hostname, port, exclList)) {
191 case Proxy.PROXY_VALID:
193 case Proxy.PROXY_HOSTNAME_EMPTY:
194 return R.string.proxy_error_empty_host_set_port;
195 case Proxy.PROXY_HOSTNAME_INVALID:
196 return R.string.proxy_error_invalid_host;
197 case Proxy.PROXY_PORT_EMPTY:
198 return R.string.proxy_error_empty_port;
199 case Proxy.PROXY_PORT_INVALID:
200 return R.string.proxy_error_invalid_port;
201 case Proxy.PROXY_EXCLLIST_INVALID:
202 return R.string.proxy_error_invalid_exclusion_list;
204 // should neven happen
205 Log.e(TAG, "Unknown proxy settings error");
211 * returns true on success, false if the user must correct something
215 String hostname = mHostnameField.getText().toString().trim();
216 String portStr = mPortField.getText().toString().trim();
217 String exclList = mExclusionListField.getText().toString().trim();
220 int result = validate(hostname, portStr, exclList);
222 showDialog(ERROR_DIALOG_ID);
226 if (portStr.length() > 0) {
228 port = Integer.parseInt(portStr);
229 } catch (NumberFormatException ex) {
230 // should never happen - caught by validate above
234 ProxyInfo p = new ProxyInfo(hostname, port, exclList);
235 // FIXME: The best solution would be to make a better UI that would
236 // disable editing of the text boxes if the user chooses to use the
237 // default settings. i.e. checking a box to always use the default
238 // carrier. http:/b/issue?id=756480
239 // FIXME: If the user types in a proxy that matches the default, should
240 // we keep that setting? Can be fixed with a new UI.
241 ConnectivityManager cm =
242 (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
244 cm.setGlobalProxy(p);
248 OnClickListener mOKHandler = new OnClickListener() {
249 public void onClick(View v) {
251 getActivity().onBackPressed();
256 OnClickListener mClearHandler = new OnClickListener() {
257 public void onClick(View v) {
258 mHostnameField.setText("");
259 mPortField.setText("");
260 mExclusionListField.setText("");
264 OnClickListener mDefaultHandler = new OnClickListener() {
265 public void onClick(View v) {
266 // TODO: populate based on connection status
271 OnFocusChangeListener mOnFocusChangeHandler = new OnFocusChangeListener() {
272 public void onFocusChange(View v, boolean hasFocus) {
274 TextView textView = (TextView) v;
275 Selection.selectAll((Spannable) textView.getText());
281 public int getMetricsCategory() {
282 return MetricsEvent.PROXY_SELECTOR;