diff options
28 files changed, 657 insertions, 109 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 1094cf4..01480f8 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -189,6 +189,7 @@ </activity> <activity android:name=".vpn.VpnSettings" + android:label="@string/vpn_settings_title" android:configChanges="orientation|keyboardHidden" android:clearTaskOnLaunch="true"> <intent-filter> @@ -196,6 +197,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> 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/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/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java index e097854..72dba1a 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; @@ -51,6 +52,7 @@ public class ApnEditor extends PreferenceActivity 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; @@ -347,19 +349,8 @@ public class ApnEditor extends PreferenceActivity 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; } @@ -414,12 +405,54 @@ public class ApnEditor extends PreferenceActivity 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/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.os.Bundle; 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.graphics.drawable.Drawable; 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 @@ public class IconPreferenceScreen extends Preference { 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 @@ public class LanguageSettings extends PreferenceActivity { private String mLastInputMethodId; private String mLastTickedInputMethodId; + + private AlertDialog mDialog = null; static public String getInputMethodIdFromKey(String key) { return key; @@ -258,29 +260,35 @@ public class LanguageSettings extends PreferenceActivity { 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 @@ public class LanguageSettings extends PreferenceActivity { 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 @@ import java.util.Map; 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 @@ public class ProgressCategory extends PreferenceCategory { 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 @@ package com.android.settings; 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 @@ public class ProxySelector extends Activity 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 @@ public class ProxySelector extends Activity 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)); + + return new AlertDialog.Builder(this) + .setTitle(R.string.proxy_error) + .setPositiveButton(R.string.proxy_error_dismiss, null) + .setMessage(msg) + .create(); + } + return super.onCreateDialog(id); + } - new AlertDialog.Builder(this) - .setTitle(R.string.proxy_error) - .setMessage(error) - .setPositiveButton(R.string.proxy_error_dismiss, null) - .show(); + @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 @@ public class ProxySelector extends Activity int result = validate(hostname, portStr); if (result > 0) { - showError(result); + showDialog(ERROR_DIALOG_ID); return false; } 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 @@ package com.android.settings; 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.location.LocationManager; 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.os.Bundle; 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 @@ public class Settings extends PreferenceActivity { 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 @@ public class Settings extends PreferenceActivity { 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/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 @@ public class SettingsSafetyLegalActivity extends AlertActivity private WebView mWebView; + private AlertDialog mErrorDialog = null; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -85,14 +87,31 @@ public class SettingsSafetyLegalActivity extends AlertActivity } 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..a735268 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; diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java index 9eee4e0..b924571 100644 --- a/src/com/android/settings/TetherSettings.java +++ b/src/com/android/settings/TetherSettings.java @@ -21,7 +21,6 @@ import com.android.settings.wifi.WifiApEnabler; 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.CheckBoxPreference; 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 @@ public class TetherSettings extends PreferenceActivity { private BroadcastReceiver mTetherChangeReceiver; private String[] mUsbRegexs; - private ArrayList mUsbIfaces; private String[] mWifiRegexs; @@ -161,7 +157,8 @@ public class TetherSettings extends PreferenceActivity { 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 @@ public class TetherSettings extends PreferenceActivity { 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 @@ public class TetherSettings extends PreferenceActivity { 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 @@ public class TetherSettings extends PreferenceActivity { } } } - 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 @@ import android.widget.AdapterView.OnItemSelectedListener; */ 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..b29ec06 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -22,8 +22,14 @@ import android.content.pm.ApplicationInfo; 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 class Utils { 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 @@ public class Utils { } /** + * 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 1e73b2d..78c531c 100644 --- a/src/com/android/settings/bluetooth/BluetoothSettings.java +++ b/src/com/android/settings/bluetooth/BluetoothSettings.java @@ -188,7 +188,8 @@ public class BluetoothSettings extends PreferenceActivity super.onPause(); 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 32f7ff3..d778f11 100644 --- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java +++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java @@ -67,6 +67,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> private final LocalBluetoothManager mLocalManager; + private AlertDialog mDialog = null; + private List<Callback> mCallbacks = new ArrayList<Callback>(); /** @@ -201,12 +203,29 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> } }; - 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 @@ public class QuickLaunchSettings extends PreferenceActivity implements 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 @@ public class QuickLaunchSettings extends PreferenceActivity implements 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 @@ package com.android.settings.vpn; 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 @@ import android.view.View; 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 @@ public class VpnEditor extends PreferenceActivity { case MENU_CANCEL: if (profileChanged()) { - showCancellationConfirmDialog(); + showDialog(CONFIRM_DIALOG_ID); } else { finish(); } @@ -171,21 +173,39 @@ public class VpnEditor extends PreferenceActivity { } } - 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 Binary files differnew file mode 100755 index 0000000..5cea33f --- /dev/null +++ b/tests/res/drawable/ic_settings_applications.png 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); + } + +} |