am 7ab66973: Merge "DO NOT MERGE Show user dialog for BT." into gingerbread
* commit '7ab66973a973b9d23c411bf1c6631fa93c4903bf':
DO NOT MERGE Show user dialog for BT.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4a1bfc3..48f2a74 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -207,6 +207,7 @@
</activity>
<activity android:name=".vpn.VpnSettings"
+ android:label="@string/vpn_settings_title"
android:configChanges="orientation|keyboardHidden"
android:clearTaskOnLaunch="true">
<intent-filter>
@@ -214,6 +215,7 @@
<action android:name="android.net.vpn.SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE_LAUNCH" />
+ <category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
</activity>
@@ -343,7 +345,8 @@
<activity android:name="SettingsLicenseActivity"
android:label="@string/settings_license_activity_title"
- android:theme="@*android:style/Theme.Dialog.Alert">
+ android:theme="@*android:style/Theme.Dialog.Alert"
+ android:configChanges="orientation">
<intent-filter>
<action android:name="android.settings.LICENSE" />
<category android:name="android.intent.category.DEFAULT" />
diff --git a/res/layout/bluetooth_pin_entry.xml b/res/layout/bluetooth_pin_entry.xml
index 16b75fc..b0c1216 100644
--- a/res/layout/bluetooth_pin_entry.xml
+++ b/res/layout/bluetooth_pin_entry.xml
@@ -44,8 +44,9 @@
android:layout_marginTop="20dip"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
+ android:inputType="textPassword"
android:singleLine="true" />
</LinearLayout>
-</ScrollView>
\ No newline at end of file
+</ScrollView>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4a7aa66..44246dc 100755
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -177,6 +177,8 @@
<string name="battery_info_health_over_voltage">Over voltage</string>
<!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="battery_info_health_unspecified_failure">Unknown error</string>
+ <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="battery_info_health_cold">Cold</string>
<!-- Used as setting title (for checkbox) on second screen after selecting Bluetooth settings -->
<string name="bluetooth">Bluetooth</string>
diff --git a/res/xml/apn_editor.xml b/res/xml/apn_editor.xml
index 287a6f8..f000dd0 100644
--- a/res/xml/apn_editor.xml
+++ b/res/xml/apn_editor.xml
@@ -22,7 +22,7 @@
android:dialogTitle="@string/apn_name"
android:key="apn_name"
android:singleLine="true"
- android:inputType="textEmailAddress"
+ android:inputType="text"
/>
<EditTextPreference
android:title="@string/apn_apn"
diff --git a/res/xml/settings.xml b/res/xml/settings.xml
index 8c92870..6ddbf7c 100644
--- a/res/xml/settings.xml
+++ b/res/xml/settings.xml
@@ -20,6 +20,20 @@
android:title="@string/settings_label"
android:key="parent">
+ <!-- Operator hook -->
+
+ <com.android.settings.IconPreferenceScreen
+ android:key="operator_settings">
+ <intent android:action="com.android.settings.OPERATOR_APPLICATION_SETTING" />
+ </com.android.settings.IconPreferenceScreen>
+
+ <!-- Manufacturer hook -->
+
+ <com.android.settings.IconPreferenceScreen
+ android:key="manufacturer_settings">
+ <intent android:action="com.android.settings.MANUFACTURER_APPLICATION_SETTING" />
+ </com.android.settings.IconPreferenceScreen>
+
<com.android.settings.IconPreferenceScreen
android:title="@string/radio_controls_title"
settings:icon="@drawable/ic_settings_wireless">
diff --git a/res/xml/sim_lock_settings.xml b/res/xml/sim_lock_settings.xml
index b2ecb11..8c3a0a0 100644
--- a/res/xml/sim_lock_settings.xml
+++ b/res/xml/sim_lock_settings.xml
@@ -25,6 +25,7 @@
android:summaryOff="@string/sim_lock_off"/>
<com.android.settings.EditPinPreference
android:key="sim_pin"
+ android:dependency="sim_toggle"
android:title="@string/sim_pin_change"
android:dialogTitle="@string/sim_change_pin"
android:dialogMessage="@string/sim_enter_old"
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index 4ac7401..0dbc99f 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -17,6 +17,7 @@
package com.android.settings;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
@@ -53,6 +54,7 @@
private static final int MENU_DELETE = Menu.FIRST;
private static final int MENU_SAVE = Menu.FIRST + 1;
private static final int MENU_CANCEL = Menu.FIRST + 2;
+ private static final int ERROR_DIALOG_ID = 0;
private static String sNotSet;
private EditTextPreference mName;
@@ -240,6 +242,8 @@
int authVal = mCursor.getInt(AUTH_TYPE_INDEX);
if (authVal != -1) {
mAuthType.setValueIndex(authVal);
+ } else {
+ mAuthType.setValue(null);
}
mProtocol.setValue(mCursor.getString(PROTOCOL_INDEX));
@@ -388,19 +392,8 @@
String mcc = checkNotSet(mMcc.getText());
String mnc = checkNotSet(mMnc.getText());
- String errorMsg = null;
- if (name.length() < 1) {
- errorMsg = mRes.getString(R.string.error_name_empty);
- } else if (apn.length() < 1) {
- errorMsg = mRes.getString(R.string.error_apn_empty);
- } else if (mcc.length() != 3) {
- errorMsg = mRes.getString(R.string.error_mcc_not3);
- } else if ((mnc.length() & 0xFFFE) != 2) {
- errorMsg = mRes.getString(R.string.error_mnc_not23);
- }
-
- if (errorMsg != null && !force) {
- showErrorMessage(errorMsg);
+ if (getErrorMsg() != null && !force) {
+ showDialog(ERROR_DIALOG_ID);
return false;
}
@@ -462,12 +455,54 @@
return true;
}
- private void showErrorMessage(String message) {
- new AlertDialog.Builder(this)
- .setTitle(R.string.error_title)
- .setMessage(message)
- .setPositiveButton(android.R.string.ok, null)
- .show();
+ private String getErrorMsg() {
+ String errorMsg = null;
+
+ String name = checkNotSet(mName.getText());
+ String apn = checkNotSet(mApn.getText());
+ String mcc = checkNotSet(mMcc.getText());
+ String mnc = checkNotSet(mMnc.getText());
+
+ if (name.length() < 1) {
+ errorMsg = mRes.getString(R.string.error_name_empty);
+ } else if (apn.length() < 1) {
+ errorMsg = mRes.getString(R.string.error_apn_empty);
+ } else if (mcc.length() != 3) {
+ errorMsg = mRes.getString(R.string.error_mcc_not3);
+ } else if ((mnc.length() & 0xFFFE) != 2) {
+ errorMsg = mRes.getString(R.string.error_mnc_not23);
+ }
+
+ return errorMsg;
+ }
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+
+ if (id == ERROR_DIALOG_ID) {
+ String msg = getErrorMsg();
+
+ return new AlertDialog.Builder(this)
+ .setTitle(R.string.error_title)
+ .setPositiveButton(android.R.string.ok, null)
+ .setMessage(msg)
+ .create();
+ }
+
+ return super.onCreateDialog(id);
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ super.onPrepareDialog(id, dialog);
+
+ if (id == ERROR_DIALOG_ID) {
+ String msg = getErrorMsg();
+
+ if (msg != null) {
+ ((AlertDialog)dialog).setMessage(msg);
+ }
+ }
}
private void deleteApn() {
diff --git a/src/com/android/settings/BatteryInfo.java b/src/com/android/settings/BatteryInfo.java
index 1cbe47f..2f9d50e 100644
--- a/src/com/android/settings/BatteryInfo.java
+++ b/src/com/android/settings/BatteryInfo.java
@@ -142,6 +142,8 @@
healthString = getString(R.string.battery_info_health_over_voltage);
} else if (health == BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE) {
healthString = getString(R.string.battery_info_health_unspecified_failure);
+ } else if (health == BatteryManager.BATTERY_HEALTH_COLD) {
+ healthString = getString(R.string.battery_info_health_cold);
} else {
healthString = getString(R.string.battery_info_health_unknown);
}
diff --git a/src/com/android/settings/DateTimeSettingsSetupWizard.java b/src/com/android/settings/DateTimeSettingsSetupWizard.java
index 8dd970b..a6a60c1 100644
--- a/src/com/android/settings/DateTimeSettingsSetupWizard.java
+++ b/src/com/android/settings/DateTimeSettingsSetupWizard.java
@@ -20,7 +20,6 @@
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
-import android.widget.LinearLayout;
public class DateTimeSettingsSetupWizard extends DateTimeSettings implements OnClickListener {
private View mNextButton;
diff --git a/src/com/android/settings/IconPreferenceScreen.java b/src/com/android/settings/IconPreferenceScreen.java
index c7c5303..31abf0a 100644
--- a/src/com/android/settings/IconPreferenceScreen.java
+++ b/src/com/android/settings/IconPreferenceScreen.java
@@ -22,6 +22,7 @@
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.ImageView;
public class IconPreferenceScreen extends Preference {
@@ -48,4 +49,26 @@
imageView.setImageDrawable(mIcon);
}
}
+
+ /**
+ * Sets the icon for this Preference with a Drawable.
+ *
+ * @param icon The icon for this Preference
+ */
+ public void setIcon(Drawable icon) {
+ if ((icon == null && mIcon != null) || (icon != null && !icon.equals(mIcon))) {
+ mIcon = icon;
+ notifyChanged();
+ }
+ }
+
+ /**
+ * Returns the icon of this Preference.
+ *
+ * @return The icon.
+ * @see #setIcon(Drawable)
+ */
+ public Drawable getIcon() {
+ return mIcon;
+ }
}
diff --git a/src/com/android/settings/LanguageSettings.java b/src/com/android/settings/LanguageSettings.java
index 8ab8a0c..50c78b6 100644
--- a/src/com/android/settings/LanguageSettings.java
+++ b/src/com/android/settings/LanguageSettings.java
@@ -57,6 +57,8 @@
private String mLastInputMethodId;
private String mLastTickedInputMethodId;
+
+ private AlertDialog mDialog = null;
static public String getInputMethodIdFromKey(String key) {
return key;
@@ -258,29 +260,35 @@
if (selImi == null) {
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
- AlertDialog d = (new AlertDialog.Builder(this))
- .setTitle(android.R.string.dialog_alert_title)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getString(R.string.ime_security_warning,
- selImi.getServiceInfo().applicationInfo.loadLabel(
- getPackageManager())))
- .setCancelable(true)
- .setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- chkPref.setChecked(true);
- mLastTickedInputMethodId = id;
- }
-
- })
- .setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- }
-
- })
- .create();
- d.show();
+ if (mDialog == null) {
+ mDialog = (new AlertDialog.Builder(this))
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ chkPref.setChecked(true);
+ mLastTickedInputMethodId = id;
+ }
+
+ })
+ .setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ }
+
+ })
+ .create();
+ } else {
+ if (mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ }
+ mDialog.setMessage(getString(R.string.ime_security_warning,
+ selImi.getServiceInfo().applicationInfo.loadLabel(
+ getPackageManager())));
+ mDialog.show();
} else if (id.equals(mLastTickedInputMethodId)) {
mLastTickedInputMethodId = null;
}
@@ -305,4 +313,13 @@
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
+ }
+
}
diff --git a/src/com/android/settings/ProgressCategory.java b/src/com/android/settings/ProgressCategory.java
index 15810b3..f611137 100644
--- a/src/com/android/settings/ProgressCategory.java
+++ b/src/com/android/settings/ProgressCategory.java
@@ -26,7 +26,8 @@
public class ProgressCategory extends PreferenceCategory {
private boolean mProgress = false;
-
+ private View oldView = null;
+
public ProgressCategory(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.preference_progress_category);
@@ -41,6 +42,13 @@
int visibility = mProgress ? View.VISIBLE : View.INVISIBLE;
textView.setVisibility(visibility);
progressBar.setVisibility(visibility);
+
+ if (oldView != null) {
+ oldView.findViewById(R.id.scanning_progress).setVisibility(View.GONE);
+ oldView.findViewById(R.id.scanning_text).setVisibility(View.GONE);
+ oldView.setVisibility(View.GONE);
+ }
+ oldView = view;
}
/**
diff --git a/src/com/android/settings/ProxySelector.java b/src/com/android/settings/ProxySelector.java
index 80fe3c9..66c81c6 100644
--- a/src/com/android/settings/ProxySelector.java
+++ b/src/com/android/settings/ProxySelector.java
@@ -18,6 +18,7 @@
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Proxy;
@@ -73,6 +74,7 @@
HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
}
+ private static final int ERROR_DIALOG_ID = 0;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -84,13 +86,32 @@
populateFields(false);
}
- protected void showError(int error) {
+ @Override
+ protected Dialog onCreateDialog(int id) {
+ if (id == ERROR_DIALOG_ID) {
+ String hostname = mHostnameField.getText().toString().trim();
+ String portStr = mPortField.getText().toString().trim();
+ String msg = getString(validate(hostname, portStr));
- new AlertDialog.Builder(this)
- .setTitle(R.string.proxy_error)
- .setMessage(error)
- .setPositiveButton(R.string.proxy_error_dismiss, null)
- .show();
+ return new AlertDialog.Builder(this)
+ .setTitle(R.string.proxy_error)
+ .setPositiveButton(R.string.proxy_error_dismiss, null)
+ .setMessage(msg)
+ .create();
+ }
+ return super.onCreateDialog(id);
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ super.onPrepareDialog(id, dialog);
+
+ if (id == ERROR_DIALOG_ID) {
+ String hostname = mHostnameField.getText().toString().trim();
+ String portStr = mPortField.getText().toString().trim();
+ String msg = getString(validate(hostname, portStr));
+ ((AlertDialog)dialog).setMessage(msg);
+ }
}
void initView() {
@@ -188,7 +209,7 @@
int result = validate(hostname, portStr);
if (result > 0) {
- showError(result);
+ showDialog(ERROR_DIALOG_ID);
return false;
}
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index f0fcdd7..f1c30d0 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -774,15 +774,18 @@
sb.append("\n to ")
.append(pdp.getApn().toString());
}
- sb.append("\ninterface: ")
- .append(phone.getInterfaceName(phone.getActiveApnTypes()[0]))
- .append("\naddress: ")
- .append(phone.getIpAddress(phone.getActiveApnTypes()[0]))
- .append("\ngateway: ")
- .append(phone.getGateway(phone.getActiveApnTypes()[0]));
- String[] dns = phone.getDnsServers(phone.getActiveApnTypes()[0]);
- if (dns != null) {
- sb.append("\ndns: ").append(dns[0]).append(", ").append(dns[1]);
+ String[] activeApnTypes = phone.getActiveApnTypes();
+ if (activeApnTypes.length > 0) {
+ sb.append("\ninterface: ")
+ .append(phone.getInterfaceName(activeApnTypes[0]))
+ .append("\naddress: ")
+ .append(phone.getIpAddress(activeApnTypes[0]))
+ .append("\ngateway: ")
+ .append(phone.getGateway(activeApnTypes[0]));
+ String[] dns = phone.getDnsServers(activeApnTypes[0]);
+ if (dns != null) {
+ sb.append("\ndns: ").append(dns[0]).append(", ").append(dns[1]);
+ }
}
} else if (dc.isInactive()) {
sb.append(" disconnected with last try at ")
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 05a655a..454ea60 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -20,7 +20,6 @@
import java.util.Observable;
import java.util.Observer;
-import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
@@ -34,18 +33,15 @@
import android.os.Bundle;
import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
-import android.preference.Preference.OnPreferenceChangeListener;
import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyStore;
import android.telephony.TelephonyManager;
-import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index f07892e..d924834 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -21,7 +21,6 @@
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
-import android.telephony.TelephonyManager;
public class Settings extends PreferenceActivity {
@@ -30,13 +29,14 @@
private static final String KEY_SYNC_SETTINGS = "sync_settings";
private static final String KEY_DOCK_SETTINGS = "dock_settings";
+ private static final String KEY_OPERATOR_SETTINGS = "operator_settings";
+ private static final String KEY_MANUFACTURER_SETTINGS = "manufacturer_settings";
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
-
- int activePhoneType = TelephonyManager.getDefault().getPhoneType();
PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
Utils.updatePreferenceToSpecificActivityOrRemove(this, parent, KEY_SYNC_SETTINGS, 0);
@@ -45,6 +45,11 @@
if (getResources().getBoolean(R.bool.has_dock_settings) == false && dockSettings != null) {
parent.removePreference(dockSettings);
}
+
+ Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(this, parent,
+ KEY_OPERATOR_SETTINGS);
+ Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(this, parent,
+ KEY_MANUFACTURER_SETTINGS);
}
@Override
diff --git a/src/com/android/settings/SettingsLicenseActivity.java b/src/com/android/settings/SettingsLicenseActivity.java
index 0b809e1..99828ce 100644
--- a/src/com/android/settings/SettingsLicenseActivity.java
+++ b/src/com/android/settings/SettingsLicenseActivity.java
@@ -17,6 +17,8 @@
package com.android.settings;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Config;
@@ -24,6 +26,12 @@
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.res.Configuration;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -32,13 +40,10 @@
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-
/**
* The "dialog" that shows from "License" in the Settings app.
*/
-public class SettingsLicenseActivity extends AlertActivity {
+public class SettingsLicenseActivity extends Activity {
private static final String TAG = "SettingsLicenseActivity";
private static final boolean LOGV = false || Config.LOGV;
@@ -46,6 +51,83 @@
private static final String DEFAULT_LICENSE_PATH = "/system/etc/NOTICE.html.gz";
private static final String PROPERTY_LICENSE_PATH = "ro.config.license_path";
+ private Handler mHandler;
+ private WebView mWebView;
+ private ProgressDialog mSpinnerDlg;
+ private AlertDialog mTextDlg;
+
+ private class LicenseFileLoader implements Runnable {
+
+ private static final String INNER_TAG = "SettingsLicenseActivity.LicenseFileLoader";
+ public static final int STATUS_OK = 0;
+ public static final int STATUS_NOT_FOUND = 1;
+ public static final int STATUS_READ_ERROR = 2;
+ public static final int STATUS_EMPTY_FILE = 3;
+
+ private String mFileName;
+ private Handler mHandler;
+
+ public LicenseFileLoader(String fileName, Handler handler) {
+ mFileName = fileName;
+ mHandler = handler;
+ }
+
+ public void run() {
+
+ int status = STATUS_OK;
+
+ InputStreamReader inputReader = null;
+ StringBuilder data = new StringBuilder(2048);
+ try {
+ char[] tmp = new char[2048];
+ int numRead;
+ if (mFileName.endsWith(".gz")) {
+ inputReader = new InputStreamReader(
+ new GZIPInputStream(new FileInputStream(mFileName)));
+ } else {
+ inputReader = new FileReader(mFileName);
+ }
+
+ while ((numRead = inputReader.read(tmp)) >= 0) {
+ data.append(tmp, 0, numRead);
+ }
+ } catch (FileNotFoundException e) {
+ Log.e(INNER_TAG, "License HTML file not found at " + mFileName, e);
+ status = STATUS_NOT_FOUND;
+ } catch (IOException e) {
+ Log.e(INNER_TAG, "Error reading license HTML file at " + mFileName, e);
+ status = STATUS_READ_ERROR;
+ } finally {
+ try {
+ if (inputReader != null) {
+ inputReader.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ if ((status == STATUS_OK) && TextUtils.isEmpty(data)) {
+ Log.e(INNER_TAG, "License HTML is empty (from " + mFileName + ")");
+ status = STATUS_EMPTY_FILE;
+ }
+
+ // Tell the UI thread that we are finished.
+ Message msg = mHandler.obtainMessage(status, null);
+ if (status == STATUS_OK) {
+ msg.obj = data.toString();
+ }
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ public SettingsLicenseActivity() {
+ super();
+ mHandler = null;
+ mWebView = null;
+ mSpinnerDlg = null;
+ mTextDlg = null;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -57,67 +139,82 @@
return;
}
- InputStreamReader inputReader = null;
- StringBuilder data = null;
- try {
- data = new StringBuilder(2048);
- char tmp[] = new char[2048];
- int numRead;
- if (fileName.endsWith(".gz")) {
- inputReader = new InputStreamReader(
- new GZIPInputStream(new FileInputStream(fileName)));
- } else {
- inputReader = new FileReader(fileName);
- }
- while ((numRead = inputReader.read(tmp)) >= 0) {
- data.append(tmp, 0, numRead);
- }
- } catch (FileNotFoundException e) {
- Log.e(TAG, "License HTML file not found at " + fileName, e);
- showErrorAndFinish();
- return;
- } catch (IOException e) {
- Log.e(TAG, "Error reading license HTML file at " + fileName, e);
- showErrorAndFinish();
- return;
- } finally {
- try {
- if (inputReader != null) {
- inputReader.close();
- }
- } catch (IOException e) {
- }
- }
+ // The activity does not have any view itself,
+ // so set it invisible to avoid displaying the title text in the background.
+ setVisible(false);
- if (TextUtils.isEmpty(data)) {
- Log.e(TAG, "License HTML is empty (from " + fileName + ")");
- showErrorAndFinish();
- return;
- }
+ mWebView = new WebView(this);
- WebView webView = new WebView(this);
+ mHandler = new Handler() {
- // Begin the loading. This will be done in a separate thread in WebView.
- webView.loadDataWithBaseURL(null, data.toString(), "text/html", "utf-8", null);
- webView.setWebViewClient(new WebViewClient() {
@Override
- public void onPageFinished(WebView view, String url) {
- // Change from 'Loading...' to the real title
- mAlert.setTitle(getString(R.string.settings_license_activity_title));
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+
+ if (msg.what == LicenseFileLoader.STATUS_OK) {
+ String text = (String) msg.obj;
+ showPageOfText(text);
+ } else {
+ showErrorAndFinish();
+ }
+ }
+ };
+
+ CharSequence title = getText(R.string.settings_license_activity_title);
+ CharSequence msg = getText(R.string.settings_license_activity_loading);
+
+ ProgressDialog pd = ProgressDialog.show(this, title, msg, true, false);
+ pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ mSpinnerDlg = pd;
+
+ // Start separate thread to do the actual loading.
+ Thread thread = new Thread(new LicenseFileLoader(fileName, mHandler));
+ thread.start();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mTextDlg != null) {
+ mTextDlg.dismiss();
+ }
+ }
+
+ private void showPageOfText(String text) {
+ // Create an AlertDialog to display the WebView in.
+ AlertDialog.Builder builder = new AlertDialog.Builder(SettingsLicenseActivity.this);
+ builder.setCancelable(true)
+ .setView(mWebView)
+ .setTitle(R.string.settings_license_activity_title);
+
+ mTextDlg = builder.create();
+ mTextDlg.setOnDismissListener(new OnDismissListener() {
+
+ public void onDismiss(DialogInterface dlgi) {
+ SettingsLicenseActivity.this.finish();
}
});
- final AlertController.AlertParams p = mAlertParams;
- p.mTitle = getString(R.string.settings_license_activity_loading);
- p.mView = webView;
- p.mForceInverseBackground = true;
- setupAlert();
+ // Begin the loading. This will be done in a separate thread in WebView.
+ mWebView.loadDataWithBaseURL(null, text, "text/html", "utf-8", null);
+ mWebView.setWebViewClient(new WebViewClient() {
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ mSpinnerDlg.dismiss();
+ mSpinnerDlg = null;
+ mTextDlg.show();
+ mTextDlg = null;
+ }
+ });
+
+ mWebView = null;
}
private void showErrorAndFinish() {
+ mSpinnerDlg.dismiss();
+ mSpinnerDlg = null;
Toast.makeText(this, R.string.settings_license_activity_unavailable, Toast.LENGTH_LONG)
.show();
finish();
}
-
}
diff --git a/src/com/android/settings/SettingsSafetyLegalActivity.java b/src/com/android/settings/SettingsSafetyLegalActivity.java
index 0c51928..368ee1d 100644
--- a/src/com/android/settings/SettingsSafetyLegalActivity.java
+++ b/src/com/android/settings/SettingsSafetyLegalActivity.java
@@ -40,6 +40,8 @@
private WebView mWebView;
+ private AlertDialog mErrorDialog = null;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -85,14 +87,31 @@
}
private void showErrorAndFinish(String url) {
- new AlertDialog.Builder(this)
- .setMessage(getResources()
- .getString(R.string.settings_safetylegal_activity_unreachable, url))
- .setTitle(R.string.settings_safetylegal_activity_title)
- .setPositiveButton(android.R.string.ok, this)
- .setOnCancelListener(this)
- .setCancelable(true)
- .show();
+ if (mErrorDialog == null) {
+ mErrorDialog = new AlertDialog.Builder(this)
+ .setTitle(R.string.settings_safetylegal_activity_title)
+ .setPositiveButton(android.R.string.ok, this)
+ .setOnCancelListener(this)
+ .setCancelable(true)
+ .create();
+ } else {
+ if (mErrorDialog.isShowing()) {
+ mErrorDialog.dismiss();
+ }
+ }
+ mErrorDialog.setMessage(getResources()
+ .getString(R.string.settings_safetylegal_activity_unreachable, url));
+ mErrorDialog.show();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (mErrorDialog != null) {
+ mErrorDialog.dismiss();
+ mErrorDialog = null;
+ }
}
@Override
diff --git a/src/com/android/settings/SoundSettings.java b/src/com/android/settings/SoundSettings.java
index bfb5566..2984684 100644
--- a/src/com/android/settings/SoundSettings.java
+++ b/src/com/android/settings/SoundSettings.java
@@ -16,8 +16,6 @@
package com.android.settings;
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -320,8 +318,8 @@
public boolean onPreferenceChange(Preference preference, Object objValue) {
final String key = preference.getKey();
if (KEY_EMERGENCY_TONE.equals(key)) {
- int value = Integer.parseInt((String) objValue);
try {
+ int value = Integer.parseInt((String) objValue);
Settings.System.putInt(getContentResolver(),
Settings.System.EMERGENCY_TONE, value);
} catch (NumberFormatException e) {
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 6764c4c..22377ab 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -21,7 +21,6 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Bundle;
-import android.os.SystemProperties;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -33,8 +32,6 @@
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
-import android.provider.Settings;
-import android.util.Log;
import android.webkit.WebView;
import java.io.InputStream;
@@ -67,7 +64,6 @@
private BroadcastReceiver mTetherChangeReceiver;
private String[] mUsbRegexs;
- private ArrayList mUsbIfaces;
private String[] mWifiRegexs;
@@ -161,7 +157,8 @@
ConnectivityManager.EXTRA_ACTIVE_TETHER);
ArrayList<String> errored = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ERRORED_TETHER);
- updateState(available.toArray(), active.toArray(), errored.toArray());
+ updateState((String[]) available.toArray(), (String[]) active.toArray(),
+ (String[]) errored.toArray());
} else if (intent.getAction().equals(Intent.ACTION_MEDIA_SHARED) ||
intent.getAction().equals(Intent.ACTION_MEDIA_UNSHARED)) {
updateState();
@@ -205,8 +202,8 @@
updateState(available, tethered, errored);
}
- private void updateState(Object[] available, Object[] tethered,
- Object[] errored) {
+ private void updateState(String[] available, String[] tethered,
+ String[] errored) {
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
boolean usbTethered = false;
@@ -215,8 +212,7 @@
boolean usbErrored = false;
boolean massStorageActive =
Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
- for (Object o : available) {
- String s = (String)o;
+ for (String s : available) {
for (String regex : mUsbRegexs) {
if (s.matches(regex)) {
usbAvailable = true;
@@ -226,14 +222,12 @@
}
}
}
- for (Object o : tethered) {
- String s = (String)o;
+ for (String s : tethered) {
for (String regex : mUsbRegexs) {
if (s.matches(regex)) usbTethered = true;
}
}
- for (Object o: errored) {
- String s = (String)o;
+ for (String s: errored) {
for (String regex : mUsbRegexs) {
if (s.matches(regex)) usbErrored = true;
}
diff --git a/src/com/android/settings/UsageStats.java b/src/com/android/settings/UsageStats.java
index fcb6990..f67eeec 100755
--- a/src/com/android/settings/UsageStats.java
+++ b/src/com/android/settings/UsageStats.java
@@ -52,7 +52,7 @@
*/
public class UsageStats extends Activity implements OnItemSelectedListener {
private static final String TAG="UsageStatsActivity";
- private static final boolean localLOGV = true;
+ private static final boolean localLOGV = false;
private Spinner mTypeSpinner;
private ListView mListView;
private IUsageStats mUsageStatsService;
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index d4f1f11..b29ec06f 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -22,8 +22,14 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.SystemProperties;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceGroup;
+import android.text.TextUtils;
import java.util.List;
@@ -35,6 +41,24 @@
public static final int UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY = 1;
/**
+ * Name of the meta-data item that should be set in the AndroidManifest.xml
+ * to specify the icon that should be displayed for the preference.
+ */
+ private static final String META_DATA_PREFERENCE_ICON = "com.android.settings.icon";
+
+ /**
+ * Name of the meta-data item that should be set in the AndroidManifest.xml
+ * to specify the title that should be displayed for the preference.
+ */
+ private static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";
+
+ /**
+ * Name of the meta-data item that should be set in the AndroidManifest.xml
+ * to specify the summary text that should be displayed for the preference.
+ */
+ private static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";
+
+ /**
* Finds a matching activity for a preference's intent. If a matching
* activity is not found, it will remove the preference.
*
@@ -90,10 +114,97 @@
}
/**
+ * Finds a matching activity for a preference's intent. If a matching
+ * activity is not found, it will remove the preference. The icon, title and
+ * summary of the preference will also be updated with the values retrieved
+ * from the activity's meta-data elements. If no meta-data elements are
+ * specified then the preference title will be set to match the label of the
+ * activity, an icon and summary text will not be displayed.
+ *
+ * @param context The context.
+ * @param parentPreferenceGroup The preference group that contains the
+ * preference whose intent is being resolved.
+ * @param preferenceKey The key of the preference whose intent is being
+ * resolved.
+ *
+ * @return Whether an activity was found. If false, the preference was
+ * removed.
+ *
+ * @see {@link #META_DATA_PREFERENCE_ICON}
+ * {@link #META_DATA_PREFERENCE_TITLE}
+ * {@link #META_DATA_PREFERENCE_SUMMARY}
+ */
+ public static boolean updatePreferenceToSpecificActivityFromMetaDataOrRemove(Context context,
+ PreferenceGroup parentPreferenceGroup, String preferenceKey) {
+
+ IconPreferenceScreen preference = (IconPreferenceScreen)parentPreferenceGroup
+ .findPreference(preferenceKey);
+ if (preference == null) {
+ return false;
+ }
+
+ Intent intent = preference.getIntent();
+ if (intent != null) {
+ // Find the activity that is in the system image
+ PackageManager pm = context.getPackageManager();
+ List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+ int listSize = list.size();
+ for (int i = 0; i < listSize; i++) {
+ ResolveInfo resolveInfo = list.get(i);
+ if ((resolveInfo.activityInfo.applicationInfo.flags
+ & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ Drawable icon = null;
+ String title = null;
+ String summary = null;
+
+ // Get the activity's meta-data
+ try {
+ Resources res = pm
+ .getResourcesForApplication(resolveInfo.activityInfo.packageName);
+ Bundle metaData = resolveInfo.activityInfo.metaData;
+
+ if (res != null && metaData != null) {
+ icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
+ title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
+ summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
+ }
+ } catch (NameNotFoundException e) {
+ // Ignore
+ } catch (NotFoundException e) {
+ // Ignore
+ }
+
+ // Set the preference title to the activity's label if no
+ // meta-data is found
+ if (TextUtils.isEmpty(title)) {
+ title = resolveInfo.loadLabel(pm).toString();
+ }
+
+ // Set icon, title and summary for the preference
+ preference.setIcon(icon);
+ preference.setTitle(title);
+ preference.setSummary(summary);
+
+ // Replace the intent with this specific activity
+ preference.setIntent(new Intent().setClassName(
+ resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name));
+
+ return true;
+ }
+ }
+ }
+
+ // Did not find a matching activity, so remove the preference
+ parentPreferenceGroup.removePreference(preference);
+
+ return false;
+ }
+
+ /**
* Returns true if Monkey is running.
*/
public static boolean isMonkeyRunning() {
return SystemProperties.getBoolean("ro.monkey", false);
}
-
}
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index e897673..2eb3b17 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -166,8 +166,6 @@
// Repopulate (which isn't too bad since it's cached in the settings
// bluetooth manager
- mDevicePreferenceMap.clear();
- mDeviceList.removeAll();
addDevices();
if (mScreenType == SCREEN_TYPE_SETTINGS) {
@@ -192,8 +190,12 @@
protected void onPause() {
super.onPause();
- mLocalManager.setForegroundActivity(null);
+ mDevicePreferenceMap.clear();
+ mDeviceList.removeAll();
+ mLocalManager.setForegroundActivity(null);
+ mDevicePreferenceMap.clear();
+ mDeviceList.removeAll();
unregisterReceiver(mReceiver);
mLocalManager.unregisterCallback(this);
diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
index f8d25ac..26bb4e8 100644
--- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
+++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
@@ -67,6 +67,8 @@
private final LocalBluetoothManager mLocalManager;
+ private AlertDialog mDialog = null;
+
private List<Callback> mCallbacks = new ArrayList<Callback>();
/**
@@ -194,12 +196,29 @@
}
};
- new AlertDialog.Builder(context)
- .setTitle(getName())
- .setMessage(message)
- .setPositiveButton(android.R.string.ok, disconnectListener)
- .setNegativeButton(android.R.string.cancel, null)
- .show();
+ if (mDialog == null) {
+ mDialog = new AlertDialog.Builder(context)
+ .setPositiveButton(android.R.string.ok, disconnectListener)
+ .setNegativeButton(android.R.string.cancel, null)
+ .create();
+ } else {
+ if (mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ }
+ mDialog.setTitle(getName());
+ mDialog.setMessage(message);
+ mDialog.show();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
+
+ super.finalize();
}
public void connect() {
diff --git a/src/com/android/settings/quicklaunch/QuickLaunchSettings.java b/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
index ca5d3ab..2d2b01c 100644
--- a/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
+++ b/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
@@ -204,7 +204,7 @@
return true;
}
- public boolean onItemLongClick(AdapterView parent, View view, int position, long id) {
+ public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// Open the clear shortcut dialog
Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(position);
@@ -314,7 +314,7 @@
String intentUri = c.getString(intentColumn);
PackageManager packageManager = getPackageManager();
try {
- Intent intent = Intent.getIntent(intentUri);
+ Intent intent = Intent.parseUri(intentUri, 0);
ResolveInfo info = packageManager.resolveActivity(intent, 0);
if (info != null) {
title = info.loadLabel(packageManager);
diff --git a/src/com/android/settings/vpn/VpnEditor.java b/src/com/android/settings/vpn/VpnEditor.java
index 497f4bf..349befb 100644
--- a/src/com/android/settings/vpn/VpnEditor.java
+++ b/src/com/android/settings/vpn/VpnEditor.java
@@ -19,6 +19,7 @@
import com.android.settings.R;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.vpn.L2tpIpsecProfile;
@@ -44,6 +45,7 @@
public class VpnEditor extends PreferenceActivity {
private static final int MENU_SAVE = Menu.FIRST;
private static final int MENU_CANCEL = Menu.FIRST + 1;
+ private static final int CONFIRM_DIALOG_ID = 0;
private static final String KEY_PROFILE = "profile";
private static final String KEY_ORIGINAL_PROFILE_NAME = "orig_profile_name";
@@ -98,7 +100,7 @@
case MENU_CANCEL:
if (profileChanged()) {
- showCancellationConfirmDialog();
+ showDialog(CONFIRM_DIALOG_ID);
} else {
finish();
}
@@ -171,21 +173,39 @@
}
}
- private void showCancellationConfirmDialog() {
- new AlertDialog.Builder(this)
- .setTitle(android.R.string.dialog_alert_title)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(mAddingProfile
- ? R.string.vpn_confirm_add_profile_cancellation
- : R.string.vpn_confirm_edit_profile_cancellation)
- .setPositiveButton(R.string.vpn_yes_button,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int w) {
- finish();
- }
- })
- .setNegativeButton(R.string.vpn_mistake_button, null)
- .show();
+
+ @Override
+ protected Dialog onCreateDialog(int id) {
+
+ if (id == CONFIRM_DIALOG_ID) {
+ return new AlertDialog.Builder(this)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(mAddingProfile
+ ? R.string.vpn_confirm_add_profile_cancellation
+ : R.string.vpn_confirm_edit_profile_cancellation)
+ .setPositiveButton(R.string.vpn_yes_button,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int w) {
+ finish();
+ }
+ })
+ .setNegativeButton(R.string.vpn_mistake_button, null)
+ .create();
+ }
+
+ return super.onCreateDialog(id);
+ }
+
+ @Override
+ protected void onPrepareDialog(int id, Dialog dialog) {
+ super.onPrepareDialog(id, dialog);
+
+ if (id == CONFIRM_DIALOG_ID) {
+ ((AlertDialog)dialog).setMessage(mAddingProfile
+ ? getString(R.string.vpn_confirm_add_profile_cancellation)
+ : getString(R.string.vpn_confirm_edit_profile_cancellation));
+ }
}
private VpnProfile getProfile() {
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 6f0b5ef..53bf40f 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -30,8 +30,29 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name="Operator" android:label="Operator Hook Test" >
+ <intent-filter>
+ <action android:name="com.android.settings.OPERATOR_APPLICATION_SETTING" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.title" android:resource="@string/operator_settings_title" />
+ <meta-data android:name="com.android.settings.summary" android:resource="@string/operator_settings_summary" />
+ <meta-data android:name="com.android.settings.icon" android:resource="@drawable/ic_settings_applications" />
+ </activity>
+ <activity android:name="Manufacturer" android:label="Manufacturer Hook Test" >
+ <intent-filter>
+ <action android:name="com.android.settings.MANUFACTURER_APPLICATION_SETTING" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.title" android:resource="@string/manufacturer_settings_title" />
+ <meta-data android:name="com.android.settings.summary" android:resource="@string/manufacturer_settings_summary" />
+ <meta-data android:name="com.android.settings.icon" android:resource="@drawable/ic_settings_applications" />
+ </activity>
</application>
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.settings"
+ android:label="Settings App Tests">
+ </instrumentation>
+
<instrumentation android:name="SettingsLaunchPerformance"
android:targetPackage="com.android.settings"
android:label="Settings Launch Performance">
diff --git a/tests/res/drawable/ic_settings_applications.png b/tests/res/drawable/ic_settings_applications.png
new file mode 100755
index 0000000..5cea33f
--- /dev/null
+++ b/tests/res/drawable/ic_settings_applications.png
Binary files differ
diff --git a/tests/res/layout/manufacturer_main.xml b/tests/res/layout/manufacturer_main.xml
new file mode 100644
index 0000000..8f8c48f
--- /dev/null
+++ b/tests/res/layout/manufacturer_main.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TextView android:layout_width="fill_parent"
+ android:layout_height="wrap_content" android:text="@string/manufacturer_hello" />
+</LinearLayout>
diff --git a/tests/res/layout/operator_main.xml b/tests/res/layout/operator_main.xml
new file mode 100644
index 0000000..3cf8e00
--- /dev/null
+++ b/tests/res/layout/operator_main.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TextView android:layout_width="fill_parent"
+ android:layout_height="wrap_content" android:text="@string/operator_hello" />
+</LinearLayout>
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
index 00de425..9fb98f9 100644
--- a/tests/res/values/strings.xml
+++ b/tests/res/values/strings.xml
@@ -22,4 +22,10 @@
<string name="discoverable">Discoverable</string>
<string name="start_scan">Start scan</string>
<string name="stop_scan">Stop scan</string>
+ <string name="operator_hello">Hello Operator!</string>
+ <string name="operator_settings_title">Operator</string>
+ <string name="operator_settings_summary">Operator hook that can be used to start activity of choice</string>
+ <string name="manufacturer_hello">Hello Manufacturer!</string>
+ <string name="manufacturer_settings_title">Manufacturer</string>
+ <string name="manufacturer_settings_summary">Manufacturer hook that can be used to start activity of choice</string>
</resources>
diff --git a/tests/src/com/android/settings/SettingsHookTests.java b/tests/src/com/android/settings/SettingsHookTests.java
new file mode 100644
index 0000000..b14e5bc
--- /dev/null
+++ b/tests/src/com/android/settings/SettingsHookTests.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2010 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 com.android.settings.tests.Manufacturer;
+import com.android.settings.tests.Operator;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+import android.test.ActivityInstrumentationTestCase2;
+
+import java.util.List;
+
+/**
+ * Tests for the Settings operator/manufacturer hook.
+ *
+ * Running all tests:
+ *
+ * make SettingsTests
+ * adb push SettingsTests.apk /system/app/SettingsTests.apk
+ * adb shell am instrument \
+ * -w com.android.settings.tests/android.test.InstrumentationTestRunner
+ */
+public class SettingsHookTests extends ActivityInstrumentationTestCase2<Settings> {
+
+ private static final String PACKAGE_NAME = "com.android.settings.tests";
+
+ private static final String KEY_SETTINGS_ROOT = "parent";
+ private static final String KEY_SETTINGS_OPERATOR = "operator_settings";
+ private static final String KEY_SETTINGS_MANUFACTURER = "manufacturer_settings";
+
+ private static final String INTENT_OPERATOR_HOOK = "com.android.settings.OPERATOR_APPLICATION_SETTING";
+ private static final String INTENT_MANUFACTURER_HOOK = "com.android.settings.MANUFACTURER_APPLICATION_SETTING";
+
+ private Settings mSettings;
+
+ public SettingsHookTests() {
+ super("com.android.settings", Settings.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mSettings = getActivity();
+ }
+
+ /**
+ * Test that the operator/manufacturer settings hook test application is
+ * available and that it's installed in the device's system image.
+ */
+ public void testSettingsHookTestAppAvailable() throws Exception {
+ Context context = mSettings.getApplicationContext();
+ PackageManager pm = context.getPackageManager();
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(PACKAGE_NAME, 0);
+ assertTrue((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+ }
+
+ /**
+ * Test that the operator test activity has registered an intent-filter for
+ * an action named 'android.settings.OPERATOR_APPLICATION_SETTING'.
+ */
+ public void testOperatorIntentFilter() {
+ boolean result = false;
+ Context context = mSettings.getApplicationContext();
+ PackageManager pm = context.getPackageManager();
+ Intent intent = new Intent(INTENT_OPERATOR_HOOK);
+ List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
+ for (ResolveInfo resolveInfo : list) {
+ if (resolveInfo.activityInfo.packageName.equals(PACKAGE_NAME)) {
+ result = true;
+ }
+ }
+ assertTrue("Intent-filer not found", result);
+ }
+
+ /**
+ * Test that the manufacturer test activity has registered an intent-filter
+ * for an action named 'android.settings.MANUFACTURER_APPLICATION_SETTING'.
+ */
+ public void testManufacturerIntentFilter() {
+ boolean result = false;
+ Context context = mSettings.getApplicationContext();
+ PackageManager pm = context.getPackageManager();
+ Intent intent = new Intent(INTENT_MANUFACTURER_HOOK);
+ List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
+ for (ResolveInfo resolveInfo : list) {
+ if (resolveInfo.activityInfo.packageName.equals(PACKAGE_NAME)) {
+ result = true;
+ }
+ }
+ assertTrue("Intent-filer not found", result);
+ }
+
+ /**
+ * Test that the operator preference is available in the Settings
+ * application.
+ */
+ public void testOperatorPreferenceAvailable() {
+ PreferenceGroup root = (PreferenceGroup)mSettings.findPreference(KEY_SETTINGS_ROOT);
+ Preference operatorPreference = root.findPreference(KEY_SETTINGS_OPERATOR);
+ assertNotNull(operatorPreference);
+ }
+
+ /**
+ * Test that the manufacturer preference is available in the Settings
+ * application.
+ */
+ public void testManufacturerPreferenceAvailable() {
+ PreferenceGroup root = (PreferenceGroup)mSettings.findPreference(KEY_SETTINGS_ROOT);
+ Preference manufacturerHook = root.findPreference(KEY_SETTINGS_MANUFACTURER);
+ assertNotNull(manufacturerHook);
+ }
+
+}
diff --git a/tests/src/com/android/settings/tests/Manufacturer.java b/tests/src/com/android/settings/tests/Manufacturer.java
new file mode 100644
index 0000000..692e6a8
--- /dev/null
+++ b/tests/src/com/android/settings/tests/Manufacturer.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 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.tests;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Manufacturer extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.manufacturer_main);
+ }
+}
diff --git a/tests/src/com/android/settings/tests/Operator.java b/tests/src/com/android/settings/tests/Operator.java
new file mode 100644
index 0000000..8a34363
--- /dev/null
+++ b/tests/src/com/android/settings/tests/Operator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010 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.tests;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Operator extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.operator_main);
+ }
+
+}