appList = getInstalledApps(mSortOrder);
+ mAppInfoAdapter = new AppInfoAdapter(this, appList);
+ ListView lv= (ListView) findViewById(android.R.id.list);
+ lv.setOnItemClickListener(this);
+ lv.setSaveEnabled(true);
+ lv.setItemsCanFocus(true);
+ lv.setOnItemClickListener(this);
+ mListView = lv;
+ showLoadingMsg();
}
- private void showLoadingMsg() {
- if (mLoadingDlg != null) {
- if(localLOGV) Log.i(TAG, "Displaying Loading message");
- mLoadingDlg.show();
+ @Override
+ public Dialog onCreateDialog(int id) {
+ if (id == DLG_LOADING) {
+ ProgressDialog dlg = new ProgressDialog(this);
+ dlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ dlg.setMessage(getText(R.string.loading));
+ dlg.setIndeterminate(true);
+ dlg.setOnCancelListener(this);
+ return dlg;
}
+ return null;
+ }
+
+
+ private void showLoadingMsg() {
+ showDialog(DLG_LOADING);
+ if(localLOGV) Log.i(TAG, "Displaying Loading message");
}
private void dismissLoadingMsg() {
- if ((mLoadingDlg != null) && (mLoadingDlg.isShowing())) {
- if(localLOGV) Log.i(TAG, "Dismissing Loading message");
- mLoadingDlg.dismiss();
- }
+ if(localLOGV) Log.i(TAG, "Dismissing Loading message");
+ dismissDialog(DLG_LOADING);
}
@Override
public void onStart() {
super.onStart();
- setContentView(R.layout.compute_sizes);
- showLoadingMsg();
// Create a thread to load resources
mResourceThread = new ResourceLoaderThread();
- sendMessageToHandler(COMPUTE_PKG_SIZE_START);
+ sendMessageToHandler(INIT_PKG_INFO);
+ // register receiver
+ mReceiver.registerReceiver();
}
@Override
@@ -1079,6 +1278,12 @@ public class ManageApplications extends ListActivity implements
mAppPropCache = mAppInfoAdapter.mAppPropMap;
}
+ // Avoid the restart and pause when orientation changes
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ }
+
/*
* comparator class used to sort AppInfo objects based on size
*/
@@ -1106,13 +1311,11 @@ public class ManageApplications extends ListActivity implements
}
// utility method used to start sub activity
- private void startApplicationDetailsActivity(ApplicationInfo info, PackageStats ps) {
+ private void startApplicationDetailsActivity() {
// Create intent to start new activity
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClass(this, InstalledAppDetails.class);
- mCurrentPkgName = info.packageName;
intent.putExtra(APP_PKG_NAME, mCurrentPkgName);
- intent.putExtra(APP_PKG_SIZE, ps);
// start new activity to display extended information
startActivityForResult(intent, INSTALLED_APP_DETAILS);
}
@@ -1123,43 +1326,73 @@ public class ManageApplications extends ListActivity implements
.setIcon(android.R.drawable.ic_menu_sort_alphabetically);
menu.add(0, SORT_ORDER_SIZE, 2, R.string.sort_order_size)
.setIcon(android.R.drawable.ic_menu_sort_by_size);
- menu.add(0, FILTER_APPS_ALL, 3, R.string.filter_apps_all);
- menu.add(0, FILTER_APPS_RUNNING, 4, R.string.filter_apps_running);
- menu.add(0, FILTER_APPS_THIRD_PARTY, 5, R.string.filter_apps_third_party);
+ menu.add(0, FILTER_OPTIONS, 3, R.string.filter)
+ .setIcon(R.drawable.ic_menu_filter_settings);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- if (mDoneIniting) {
+ if (mFirst) {
menu.findItem(SORT_ORDER_ALPHA).setVisible(mSortOrder != SORT_ORDER_ALPHA);
menu.findItem(SORT_ORDER_SIZE).setVisible(mSortOrder != SORT_ORDER_SIZE);
- menu.findItem(FILTER_APPS_ALL).setVisible(mFilterApps != FILTER_APPS_ALL);
- menu.findItem(FILTER_APPS_THIRD_PARTY).setVisible(
- mFilterApps != FILTER_APPS_THIRD_PARTY);
- menu.findItem(FILTER_APPS_RUNNING).setVisible(
- mFilterApps != FILTER_APPS_RUNNING);
+ menu.findItem(FILTER_OPTIONS).setVisible(true);
return true;
- }
+ }
return false;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int menuId = item.getItemId();
- sendMessageToHandler(REORDER_LIST, menuId);
+ if ((menuId == SORT_ORDER_ALPHA) || (menuId == SORT_ORDER_SIZE)) {
+ sendMessageToHandler(REORDER_LIST, menuId);
+ } else if (menuId == FILTER_OPTIONS) {
+ if (mAlertDlg == null) {
+ mAlertDlg = new AlertDialog.Builder(this).
+ setTitle(R.string.filter_dlg_title).
+ setNeutralButton(R.string.cancel, this).
+ setSingleChoiceItems(new CharSequence[] {getText(R.string.filter_apps_all),
+ getText(R.string.filter_apps_running),
+ getText(R.string.filter_apps_third_party)},
+ -1, this).
+ create();
+ }
+ mAlertDlg.show();
+ }
return true;
}
public void onItemClick(AdapterView> parent, View view, int position,
long id) {
ApplicationInfo info = (ApplicationInfo)mAppInfoAdapter.getItem(position);
- startApplicationDetailsActivity(info, mAppInfoAdapter.getAppStats(info.packageName));
+ mCurrentPkgName = info.packageName;
+ startApplicationDetailsActivity();
}
- // onCancel call back for dialog thats displayed when data is being loaded
+ // Finish the activity if the user presses the back button to cancel the activity
public void onCancel(DialogInterface dialog) {
- mLoadingDlg = null;
finish();
}
+
+ public void onClick(DialogInterface dialog, int which) {
+ int newOption;
+ switch (which) {
+ // Make sure that values of 0, 1, 2 match options all, running, third_party when
+ // created via the AlertDialog.Builder
+ case 0:
+ newOption = FILTER_APPS_ALL;
+ break;
+ case 1:
+ newOption = FILTER_APPS_RUNNING;
+ break;
+ case 2:
+ newOption = FILTER_APPS_THIRD_PARTY;
+ break;
+ default:
+ return;
+ }
+ mAlertDlg.dismiss();
+ sendMessageToHandler(REORDER_LIST, newOption);
+ }
}
diff --git a/src/com/android/settings/MediaFormat.java b/src/com/android/settings/MediaFormat.java
new file mode 100644
index 00000000000..3594572a927
--- /dev/null
+++ b/src/com/android/settings/MediaFormat.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2008 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.internal.widget.LockPatternUtils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IMountService;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.os.Environment;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+
+/**
+ * Confirm and execute a format of the sdcard.
+ * Multiple confirmations are required: first, a general "are you sure
+ * you want to do this?" prompt, followed by a keyguard pattern trace if the user
+ * has defined one, followed by a final strongly-worded "THIS WILL ERASE EVERYTHING
+ * ON THE SD CARD" prompt. If at any time the phone is allowed to go to sleep, is
+ * locked, et cetera, then the confirmation sequence is abandoned.
+ */
+public class MediaFormat extends Activity {
+
+ private static final int KEYGUARD_REQUEST = 55;
+
+ private LayoutInflater mInflater;
+ private LockPatternUtils mLockUtils;
+
+ private View mInitialView;
+ private Button mInitiateButton;
+
+ private View mFinalView;
+ private Button mFinalButton;
+
+ /**
+ * The user has gone through the multiple confirmation, so now we go ahead
+ * and invoke the Mount Service to format the SD card.
+ */
+ private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {
+ public void onClick(View v) {
+
+ // Those monkeys kept committing suicide, so we add this property
+ // to disable going through with the format
+ if (!TextUtils.isEmpty(SystemProperties.get("ro.monkey"))) {
+ return;
+ }
+ IMountService service =
+ IMountService.Stub.asInterface(ServiceManager.getService("mount"));
+ if (service != null) {
+ try {
+ service.formatMedia(Environment.getExternalStorageDirectory().toString());
+ } catch (android.os.RemoteException e) {
+ // Intentionally blank - there's nothing we can do here
+ Log.w("MediaFormat", "Unable to invoke IMountService.formatMedia()");
+ }
+ } else {
+ Log.w("MediaFormat", "Unable to locate IMountService");
+ }
+ finish();
+ }
+ };
+
+ /**
+ * Keyguard validation is run using the standard {@link ConfirmLockPattern}
+ * component as a subactivity
+ */
+ private void runKeyguardConfirmation() {
+ final Intent intent = new Intent();
+ intent.setClassName("com.android.settings",
+ "com.android.settings.ConfirmLockPattern");
+ // supply header and footer text in the intent
+ intent.putExtra(ConfirmLockPattern.HEADER_TEXT,
+ getText(R.string.media_format_gesture_prompt));
+ intent.putExtra(ConfirmLockPattern.FOOTER_TEXT,
+ getText(R.string.media_format_gesture_explanation));
+ startActivityForResult(intent, KEYGUARD_REQUEST);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode != KEYGUARD_REQUEST) {
+ return;
+ }
+
+ // If the user entered a valid keyguard trace, present the final
+ // confirmation prompt; otherwise, go back to the initial state.
+ if (resultCode == Activity.RESULT_OK) {
+ establishFinalConfirmationState();
+ } else {
+ establishInitialState();
+ }
+ }
+
+ /**
+ * If the user clicks to begin the reset sequence, we next require a
+ * keyguard confirmation if the user has currently enabled one. If there
+ * is no keyguard available, we simply go to the final confirmation prompt.
+ */
+ private Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
+ public void onClick(View v) {
+ if (mLockUtils.isLockPatternEnabled()) {
+ runKeyguardConfirmation();
+ } else {
+ establishFinalConfirmationState();
+ }
+ }
+ };
+
+ /**
+ * Configure the UI for the final confirmation interaction
+ */
+ private void establishFinalConfirmationState() {
+ if (mFinalView == null) {
+ mFinalView = mInflater.inflate(R.layout.media_format_final, null);
+ mFinalButton =
+ (Button) mFinalView.findViewById(R.id.execute_media_format);
+ mFinalButton.setOnClickListener(mFinalClickListener);
+ }
+
+ setContentView(mFinalView);
+ }
+
+ /**
+ * In its initial state, the activity presents a button for the user to
+ * click in order to initiate a confirmation sequence. This method is
+ * called from various other points in the code to reset the activity to
+ * this base state.
+ *
+ * Reinflating views from resources is expensive and prevents us from
+ * caching widget pointers, so we use a single-inflate pattern: we lazy-
+ * inflate each view, caching all of the widget pointers we'll need at the
+ * time, then simply reuse the inflated views directly whenever we need
+ * to change contents.
+ */
+ private void establishInitialState() {
+ if (mInitialView == null) {
+ mInitialView = mInflater.inflate(R.layout.media_format_primary, null);
+ mInitiateButton =
+ (Button) mInitialView.findViewById(R.id.initiate_media_format);
+ mInitiateButton.setOnClickListener(mInitiateListener);
+ }
+
+ setContentView(mInitialView);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+
+ mInitialView = null;
+ mFinalView = null;
+ mInflater = LayoutInflater.from(this);
+ mLockUtils = new LockPatternUtils(getContentResolver());
+
+ establishInitialState();
+ }
+
+ /** Abandon all progress through the confirmation sequence by returning
+ * to the initial view any time the activity is interrupted (e.g. by
+ * idle timeout).
+ */
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ establishInitialState();
+ }
+
+}
diff --git a/src/com/android/settings/PhysicalKeyboardSettings.java b/src/com/android/settings/PhysicalKeyboardSettings.java
new file mode 100644
index 00000000000..acd0bd67724
--- /dev/null
+++ b/src/com/android/settings/PhysicalKeyboardSettings.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+package com.android.settings;
+
+import android.content.ContentResolver;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceScreen;
+import android.provider.Settings.System;
+
+public class PhysicalKeyboardSettings extends PreferenceActivity {
+
+ private final String[] mSettingsUiKey = {
+ "auto_caps",
+ "auto_replace",
+ "auto_punctuate",
+ };
+
+ // Note: Order of this array should correspond to the order of the above array
+ private final String[] mSettingsSystemId = {
+ System.TEXT_AUTO_CAPS,
+ System.TEXT_AUTO_REPLACE,
+ System.TEXT_AUTO_PUNCTUATE,
+ };
+
+ // Note: Order of this array should correspond to the order of the above array
+ private final int[] mSettingsDefault = {
+ 1,
+ 1,
+ 1,
+ };
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ addPreferencesFromResource(R.xml.keyboard_settings);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ ContentResolver resolver = getContentResolver();
+ for (int i = 0; i < mSettingsUiKey.length; i++) {
+ CheckBoxPreference pref = (CheckBoxPreference) findPreference(mSettingsUiKey[i]);
+ pref.setChecked(System.getInt(resolver, mSettingsSystemId[i],
+ mSettingsDefault[i]) > 0);
+ }
+ }
+
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+
+ // Physical keyboard stuff
+ for (int i = 0; i < mSettingsUiKey.length; i++) {
+ if (mSettingsUiKey[i].equals(preference.getKey())) {
+ System.putInt(getContentResolver(), mSettingsSystemId[i],
+ ((CheckBoxPreference)preference).isChecked()? 1 : 0);
+ return true;
+ }
+ }
+
+ return super.onPreferenceTreeClick(preferenceScreen, preference);
+ }
+
+}
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index b1ad7773b5c..5df931320fc 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -95,7 +95,6 @@ public class RadioInfo extends Activity {
private static final int MENU_ITEM_TOGGLE_DATA_ON_BOOT = 6;
private TextView mImei;
- private TextView mImsi;
private TextView number;
private TextView callState;
private TextView operatorName;
@@ -119,10 +118,12 @@ public class RadioInfo extends Activity {
private TextView mPingHostname;
private TextView mHttpClientTest;
private TextView cipherState;
+ private TextView dnsCheckState;
private EditText smsc;
private Button radioPowerButton;
private Button qxdmLogButton;
private Button cipherToggleButton;
+ private Button dnsCheckToggleButton;
private Button pingTestButton;
private Button updateSmscButton;
private Button refreshSmscButton;
@@ -405,7 +406,6 @@ public class RadioInfo extends Activity {
phone = PhoneFactory.getDefaultPhone();
mImei = (TextView) findViewById(R.id.imei);
- mImsi = (TextView) findViewById(R.id.imsi);
number = (TextView) findViewById(R.id.number);
callState = (TextView) findViewById(R.id.call);
operatorName = (TextView) findViewById(R.id.operator);
@@ -428,6 +428,7 @@ public class RadioInfo extends Activity {
received = (TextView) findViewById(R.id.received);
cipherState = (TextView) findViewById(R.id.ciphState);
smsc = (EditText) findViewById(R.id.smsc);
+ dnsCheckState = (TextView) findViewById(R.id.dnsCheckState);
mPingIpAddr = (TextView) findViewById(R.id.pingIpAddr);
mPingHostname = (TextView) findViewById(R.id.pingHostname);
@@ -454,6 +455,8 @@ public class RadioInfo extends Activity {
updateSmscButton.setOnClickListener(mUpdateSmscButtonHandler);
refreshSmscButton = (Button) findViewById(R.id.refresh_smsc);
refreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
+ dnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle);
+ dnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler);
mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);
mPhoneStateReceiver.notifySignalStrength(EVENT_SIGNAL_STRENGTH_CHANGED);
@@ -490,6 +493,7 @@ public class RadioInfo extends Activity {
updateQxdmState(null);
updateProperties();
updateCiphState();
+ updateDnsCheckState();
Log.i(TAG, "[RadioInfo] onResume: register phone & data intents");
@@ -556,7 +560,7 @@ public class RadioInfo extends Activity {
// Get the toggle-data-on-boot menu item in the right state.
item = menu.findItem(MENU_ITEM_TOGGLE_DATA_ON_BOOT);
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this.getApplication());
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
boolean value = sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
if (value) {
item.setTitle(R.string.radioInfo_menu_enableDataOnBoot);
@@ -580,7 +584,7 @@ public class RadioInfo extends Activity {
private void updateQxdmState(Boolean newQxdmStatus) {
SharedPreferences sp =
- PreferenceManager.getDefaultSharedPreferences(this.getApplication());
+ PreferenceManager.getDefaultSharedPreferences(phone.getContext());
mQxdmLogEnabled = sp.getBoolean("qxdmstatus", false);
// This is called from onCreate, onResume, and the handler when the status
// is updated.
@@ -598,14 +602,14 @@ public class RadioInfo extends Activity {
}
private void setCiphPref(boolean value) {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this.getApplication());
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean(GSMPhone.CIPHERING_KEY, value);
editor.commit();
}
private boolean getCiphPref() {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this.getApplication());
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
boolean ret = sp.getBoolean(GSMPhone.CIPHERING_KEY, true);
return ret;
}
@@ -614,6 +618,12 @@ public class RadioInfo extends Activity {
cipherState.setText(getCiphPref() ? "Ciphering ON" : "Ciphering OFF");
}
+ private void updateDnsCheckState() {
+ GSMPhone gsmPhone = (GSMPhone) phone;
+ dnsCheckState.setText(gsmPhone.isDnsCheckDisabled() ?
+ "0.0.0.0 allowed" :"0.0.0.0 not allowed");
+ }
+
private final void
updateSignalStrength() {
int state =
@@ -774,10 +784,6 @@ public class RadioInfo extends Activity {
if (s == null) s = r.getString(R.string.radioInfo_unknown);
mImei.setText(s);
- s = phone.getSubscriberId();
- if (s == null) s = r.getString(R.string.radioInfo_unknown);
- mImsi.setText(s);
-
s = phone.getLine1Number();
if (s == null) s = r.getString(R.string.radioInfo_unknown);
number.setText(s);
@@ -806,10 +812,10 @@ public class RadioInfo extends Activity {
Resources r = getResources();
try {
- int txPackets = netstat.getTxPackets();
- int rxPackets = netstat.getRxPackets();
- int txBytes = netstat.getTxBytes();
- int rxBytes = netstat.getRxBytes();
+ long txPackets = netstat.getMobileTxPackets();
+ long rxPackets = netstat.getMobileRxPackets();
+ long txBytes = netstat.getMobileTxBytes();
+ long rxBytes = netstat.getMobileRxBytes();
String packets = r.getString(R.string.radioInfo_display_packets);
String bytes = r.getString(R.string.radioInfo_display_bytes);
@@ -1038,7 +1044,7 @@ public class RadioInfo extends Activity {
};
private void toggleDataDisabledOnBoot() {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this.getApplication());
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
SharedPreferences.Editor editor = sp.edit();
boolean value = sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
editor.putBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, !value);
@@ -1114,6 +1120,14 @@ public class RadioInfo extends Activity {
}
};
+ OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
+ public void onClick(View v) {
+ GSMPhone gsmPhone = (GSMPhone) phone;
+ gsmPhone.disableDnsCheck(!gsmPhone.isDnsCheckDisabled());
+ updateDnsCheckState();
+ }
+ };
+
OnClickListener mPingButtonHandler = new OnClickListener() {
public void onClick(View v) {
updatePingState();
diff --git a/src/com/android/settings/SdCardErrorReceiver.java b/src/com/android/settings/SdCardErrorReceiver.java
deleted file mode 100644
index ba35a3c5cf3..00000000000
--- a/src/com/android/settings/SdCardErrorReceiver.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.BroadcastReceiver;
-import android.util.Log;
-import android.widget.Toast;
-
-
-/**
- * Glue class: connects AlarmAlert IntentReceiver to AlarmAlert
- * activity. Passes through Alarm ID.
- */
-public class SdCardErrorReceiver extends BroadcastReceiver {
-
- private static final String TAG = "SdCardErrorReceiver";
-
- @Override public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- final int duration = 3500;
- if (action.equals(Intent.ACTION_MEDIA_BAD_REMOVAL)) {
- Toast.makeText(context, R.string.sdcard_removal_alert_title, duration).show();
- } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTABLE)) {
- Toast.makeText(context, R.string.sdcard_unmountable_alert_title, duration).show();
- } else {
- Log.e(TAG, "unknown intent");
- }
- }
-}
diff --git a/src/com/android/settings/SdCardSettings.java b/src/com/android/settings/SdCardSettings.java
index d10166a68d3..b6935a2fe4a 100644
--- a/src/com/android/settings/SdCardSettings.java
+++ b/src/com/android/settings/SdCardSettings.java
@@ -60,6 +60,9 @@ public class SdCardSettings extends Activity
Button unmountButton = (Button)findViewById(R.id.sdcard_unmount);
unmountButton.setOnClickListener(mUnmountButtonHandler);
+ Button formatButton = (Button)findViewById(R.id.sdcard_format);
+ formatButton.setOnClickListener(mFormatButtonHandler);
+
mTotalSize = (TextView)findViewById(R.id.total);
mUsedSize = (TextView)findViewById(R.id.used);
mAvailableSize = (TextView)findViewById(R.id.available);
@@ -69,6 +72,8 @@ public class SdCardSettings extends Activity
intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SHARED);
+ intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING);
+ intentFilter.addAction(Intent.ACTION_MEDIA_NOFS);
intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
@@ -198,6 +203,15 @@ public class SdCardSettings extends Activity
}
};
+ OnClickListener mFormatButtonHandler = new OnClickListener() {
+ public void onClick(View v) {
+ try {
+ mMountService.formatMedia(Environment.getExternalStorageDirectory().toString());
+ } catch (RemoteException ex) {
+ }
+ }
+ };
+
private int mStatus;
private IMountService mMountService;
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index a0a52a2f608..867bce3e4d6 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -45,7 +45,7 @@ public class SecuritySettings extends PreferenceActivity
private static final String KEY_LOCK_ENABLED = "lockenabled";
private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
private static final String KEY_TACTILE_FEEDBACK_ENABLED = "tactilefeedback";
- private static final int CONFIRM_PATTERN_REQUEST_CODE = 55;
+ private static final int CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE = 55;
private LockPatternUtils mLockPatternUtils;
private CheckBoxPreference mLockEnabled;
@@ -63,7 +63,7 @@ public class SecuritySettings extends PreferenceActivity
private CheckBoxPreference mNetwork;
private CheckBoxPreference mGps;
private LocationManager mLocationManager;
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -256,8 +256,8 @@ public class SecuritySettings extends PreferenceActivity
@Override
protected void onClick() {
- if (isChecked() && mLockPatternUtils.savedPatternExists()) {
- confirmPatternThenDisable();
+ if (mLockPatternUtils.savedPatternExists() && isChecked()) {
+ confirmPatternThenDisableAndClear();
} else {
super.onClick();
}
@@ -268,26 +268,25 @@ public class SecuritySettings extends PreferenceActivity
* Launch screen to confirm the existing lock pattern.
* @see #onActivityResult(int, int, android.content.Intent)
*/
- private void confirmPatternThenDisable() {
+ private void confirmPatternThenDisableAndClear() {
final Intent intent = new Intent();
intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
- startActivityForResult(intent, CONFIRM_PATTERN_REQUEST_CODE);
+ startActivityForResult(intent, CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE);
}
/**
- * @see #confirmPatternThenDisable
+ * @see #confirmPatternThenDisableAndClear
*/
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- if (requestCode != CONFIRM_PATTERN_REQUEST_CODE) {
- return;
- }
+ final boolean resultOk = resultCode == Activity.RESULT_OK;
- if (resultCode == Activity.RESULT_OK) {
- mLockPatternUtils.setLockPatternEnabled(false);
+ if ((requestCode == CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE) && resultOk) {
+ mLockPatternUtils.setLockPatternEnabled(false);
+ mLockPatternUtils.saveLockPattern(null);
}
}
}
diff --git a/src/com/android/settings/SoundAndDisplaySettings.java b/src/com/android/settings/SoundAndDisplaySettings.java
index 134e84f3ca0..8905b859fd7 100644
--- a/src/com/android/settings/SoundAndDisplaySettings.java
+++ b/src/com/android/settings/SoundAndDisplaySettings.java
@@ -25,6 +25,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Bundle;
+import android.os.IMountService;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.preference.ListPreference;
@@ -49,12 +50,27 @@ public class SoundAndDisplaySettings extends PreferenceActivity implements
private static final String KEY_DTMF_TONE = "dtmf_tone";
private static final String KEY_SOUND_EFFECTS = "sound_effects";
private static final String KEY_ANIMATIONS = "animations";
+ private static final String KEY_ACCELEROMETER = "accelerometer";
+ private static final String KEY_PLAY_MEDIA_NOTIFICATION_SOUNDS = "play_media_notification_sounds";
private CheckBoxPreference mSilent;
+
+ private CheckBoxPreference mPlayMediaNotificationSounds;
+
+ private IMountService mMountService = null;
+
+ /*
+ * If we are currently in one of the silent modes (the ringer mode is set to either
+ * "silent mode" or "vibrate mode"), then toggling the "Phone vibrate"
+ * preference will switch between "silent mode" and "vibrate mode".
+ * Otherwise, it will adjust the normal ringer mode's ring or ring+vibrate
+ * setting.
+ */
private CheckBoxPreference mVibrate;
private CheckBoxPreference mDtmfTone;
private CheckBoxPreference mSoundEffects;
private CheckBoxPreference mAnimations;
+ private CheckBoxPreference mAccelerometer;
private float[] mAnimationScales;
private AudioManager mAudioManager;
@@ -64,14 +80,7 @@ public class SoundAndDisplaySettings extends PreferenceActivity implements
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
-
- int ringerMode = intent
- .getIntExtra(AudioManager.EXTRA_RINGER_MODE, AudioManager.RINGER_MODE_NORMAL);
- boolean isSilentMode = ringerMode != AudioManager.RINGER_MODE_NORMAL;
-
- if (mSilent.isChecked() != isSilentMode) {
- mSilent.setChecked(isSilentMode);
- }
+ updateState(false);
}
};
@@ -82,10 +91,14 @@ public class SoundAndDisplaySettings extends PreferenceActivity implements
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
+
+ mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
addPreferencesFromResource(R.xml.sound_and_display_settings);
mSilent = (CheckBoxPreference) findPreference(KEY_SILENT);
+ mPlayMediaNotificationSounds = (CheckBoxPreference) findPreference(KEY_PLAY_MEDIA_NOTIFICATION_SOUNDS);
+
mVibrate = (CheckBoxPreference) findPreference(KEY_VIBRATE);
mDtmfTone = (CheckBoxPreference) findPreference(KEY_DTMF_TONE);
mDtmfTone.setPersistent(false);
@@ -97,6 +110,8 @@ public class SoundAndDisplaySettings extends PreferenceActivity implements
Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0);
mAnimations = (CheckBoxPreference) findPreference(KEY_ANIMATIONS);
mAnimations.setPersistent(false);
+ mAccelerometer = (CheckBoxPreference) findPreference(KEY_ACCELEROMETER);
+ mAccelerometer.setPersistent(false);
ListPreference screenTimeoutPreference =
(ListPreference) findPreference(KEY_SCREEN_TIMEOUT);
@@ -123,17 +138,28 @@ public class SoundAndDisplaySettings extends PreferenceActivity implements
}
private void updateState(boolean force) {
- final boolean silent = mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
- final boolean phoneVibrate = mAudioManager
- .getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER)
- == AudioManager.VIBRATE_SETTING_ON;
+ final int ringerMode = mAudioManager.getRingerMode();
+ final boolean silentOrVibrateMode =
+ ringerMode != AudioManager.RINGER_MODE_NORMAL;
- if (silent != mSilent.isChecked() || force) {
- mSilent.setChecked(silent);
+ if (silentOrVibrateMode != mSilent.isChecked() || force) {
+ mSilent.setChecked(silentOrVibrateMode);
}
-
- if (phoneVibrate != mVibrate.isChecked() || force) {
- mVibrate.setChecked(phoneVibrate);
+
+ try {
+ mPlayMediaNotificationSounds.setChecked(mMountService.getPlayNotificationSounds());
+ } catch (RemoteException e) {
+ }
+
+ boolean vibrateSetting;
+ if (silentOrVibrateMode) {
+ vibrateSetting = ringerMode == AudioManager.RINGER_MODE_VIBRATE;
+ } else {
+ vibrateSetting = mAudioManager.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER)
+ == AudioManager.VIBRATE_SETTING_ON;
+ }
+ if (vibrateSetting != mVibrate.isChecked() || force) {
+ mVibrate.setChecked(vibrateSetting);
}
boolean animations = true;
@@ -142,7 +168,9 @@ public class SoundAndDisplaySettings extends PreferenceActivity implements
} catch (RemoteException e) {
}
if (mAnimationScales != null) {
- for (int i=0; i 0) {
+ // Window animations are always on.
+ mAnimationScales[0] = 1;
+ }
+ for (int i=1; i {
+ Map mAppLabelList;
+ AppNameComparator(Map appList) {
+ mAppLabelList = appList;
+ }
+ public final int compare(PkgUsageStats a, PkgUsageStats b) {
+ String alabel = mAppLabelList.get(a.packageName).toString();
+ String blabel = mAppLabelList.get(b.packageName).toString();
+ return alabel.compareTo(blabel);
+ }
+ }
+
+ public static class LaunchCountComparator implements Comparator {
+ public final int compare(PkgUsageStats a, PkgUsageStats b) {
+ // return by descending order
+ return b.launchCount - a.launchCount;
+ }
+ }
+
+ public static class UsageTimeComparator implements Comparator {
+ public final int compare(PkgUsageStats a, PkgUsageStats b) {
+ long ret = a.usageTime-b.usageTime;
+ if (ret == 0) {
+ return 0;
+ }
+ if (ret < 0) {
+ return 1;
+ }
+ return -1;
+ }
+ }
+
+ // View Holder used when displaying views
+ static class AppViewHolder {
+ TextView pkgName;
+ TextView launchCount;
+ TextView usageTime;
+ }
+
+ class UsageStatsAdapter extends BaseAdapter {
+ // Constants defining order for display order
+ private static final int _DISPLAY_ORDER_USAGE_TIME = 0;
+ private static final int _DISPLAY_ORDER_LAUNCH_COUNT = 1;
+ private static final int _DISPLAY_ORDER_APP_NAME = 2;
+
+ private int mDisplayOrder = _DISPLAY_ORDER_USAGE_TIME;
+ private List mUsageStats;
+ private LaunchCountComparator mLaunchCountComparator;
+ private UsageTimeComparator mUsageTimeComparator;
+ private AppNameComparator mAppLabelComparator;
+ private HashMap mAppLabelMap;
+
+ UsageStatsAdapter() {
+ mUsageStats = new ArrayList();
+ mAppLabelMap = new HashMap();
+ PkgUsageStats[] stats;
+ try {
+ stats = mUsageStatsService.getAllPkgUsageStats();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed initializing usage stats service");
+ return;
+ }
+ if (stats == null) {
+ return;
+ }
+ for (PkgUsageStats ps : stats) {
+ mUsageStats.add(ps);
+ // load application labels for each application
+ CharSequence label;
+ try {
+ ApplicationInfo appInfo = mPm.getApplicationInfo(ps.packageName, 0);
+ label = appInfo.loadLabel(mPm);
+ } catch (NameNotFoundException e) {
+ label = ps.packageName;
+ }
+ mAppLabelMap.put(ps.packageName, label);
+ }
+ // Sort list
+ mLaunchCountComparator = new LaunchCountComparator();
+ mUsageTimeComparator = new UsageTimeComparator();
+ mAppLabelComparator = new AppNameComparator(mAppLabelMap);
+ sortList();
+ }
+ public int getCount() {
+ return mUsageStats.size();
+ }
+
+ public Object getItem(int position) {
+ return mUsageStats.get(position);
+ }
+
+ public long getItemId(int position) {
+ return position;
+ }
+
+ public View getView(int position, View convertView, ViewGroup parent) {
+ // A ViewHolder keeps references to children views to avoid unneccessary calls
+ // to findViewById() on each row.
+ AppViewHolder holder;
+
+ // When convertView is not null, we can reuse it directly, there is no need
+ // to reinflate it. We only inflate a new View when the convertView supplied
+ // by ListView is null.
+ if (convertView == null) {
+ convertView = mInflater.inflate(R.layout.usage_stats_item, null);
+
+ // Creates a ViewHolder and store references to the two children views
+ // we want to bind data to.
+ holder = new AppViewHolder();
+ holder.pkgName = (TextView) convertView.findViewById(R.id.package_name);
+ holder.launchCount = (TextView) convertView.findViewById(R.id.launch_count);
+ holder.usageTime = (TextView) convertView.findViewById(R.id.usage_time);
+ convertView.setTag(holder);
+ } else {
+ // Get the ViewHolder back to get fast access to the TextView
+ // and the ImageView.
+ holder = (AppViewHolder) convertView.getTag();
+ }
+
+ // Bind the data efficiently with the holder
+ PkgUsageStats pkgStats = mUsageStats.get(position);
+ if (pkgStats != null) {
+ CharSequence label = mAppLabelMap.get(pkgStats.packageName);
+ holder.pkgName.setText(label);
+ holder.launchCount.setText(String.valueOf(pkgStats.launchCount));
+ holder.usageTime.setText(String.valueOf(pkgStats.usageTime)+" ms");
+ } else {
+ Log.w(TAG, "No usage stats info for package:"+pkgStats.packageName);
+ }
+ return convertView;
+ }
+
+ void sortList(int sortOrder) {
+ if (mDisplayOrder == sortOrder) {
+ // do nothing
+ return;
+ }
+ mDisplayOrder= sortOrder;
+ sortList();
+ }
+ private void sortList() {
+ if (mDisplayOrder == _DISPLAY_ORDER_USAGE_TIME) {
+ if (localLOGV) Log.i(TAG, "Sorting by usage time");
+ Collections.sort(mUsageStats, mUsageTimeComparator);
+ } else if (mDisplayOrder == _DISPLAY_ORDER_LAUNCH_COUNT) {
+ if (localLOGV) Log.i(TAG, "Sorting launch count");
+ Collections.sort(mUsageStats, mLaunchCountComparator);
+ } else if (mDisplayOrder == _DISPLAY_ORDER_APP_NAME) {
+ if (localLOGV) Log.i(TAG, "Sorting by application name");
+ Collections.sort(mUsageStats, mAppLabelComparator);
+ }
+ notifyDataSetChanged();
+ }
+ }
+
+ /** Called when the activity is first created. */
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mUsageStatsService = IUsageStats.Stub.asInterface(ServiceManager.getService("usagestats"));
+ if (mUsageStatsService == null) {
+ Log.e(TAG, "Failed to retrieve usagestats service");
+ return;
+ }
+ mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mPm = getPackageManager();
+
+ setContentView(R.layout.usage_stats);
+ mTypeSpinner = (Spinner) findViewById(R.id.typeSpinner);
+ mTypeSpinner.setOnItemSelectedListener(this);
+
+ mListView = (ListView) findViewById(R.id.pkg_list);
+ // Initialize the inflater
+
+ mAdapter = new UsageStatsAdapter();
+ mListView.setAdapter(mAdapter);
+ }
+
+ public void onItemSelected(AdapterView> parent, View view, int position,
+ long id) {
+ mAdapter.sortList(position);
+ }
+
+ public void onNothingSelected(AdapterView> parent) {
+ // do nothing
+ }
+}
+
diff --git a/src/com/android/settings/UserDictionarySettings.java b/src/com/android/settings/UserDictionarySettings.java
index 5d3c8ac37df..ef22ee14d3e 100644
--- a/src/com/android/settings/UserDictionarySettings.java
+++ b/src/com/android/settings/UserDictionarySettings.java
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2007 Google Inc.
+ * Copyright (C) 2009 Google Inc.
*
* 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
@@ -24,6 +24,7 @@ import android.content.DialogInterface;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.UserDictionary;
+import android.text.InputType;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
@@ -43,6 +44,7 @@ import java.util.Locale;
public class UserDictionarySettings extends ListActivity {
private static final String INSTANCE_KEY_DIALOG_EDITING_WORD = "DIALOG_EDITING_WORD";
+ private static final String INSTANCE_KEY_ADDED_WORD = "DIALOG_ADDED_WORD";
private static final String[] QUERY_PROJECTION = {
UserDictionary.Words._ID, UserDictionary.Words.WORD
@@ -54,6 +56,8 @@ public class UserDictionarySettings extends ListActivity {
+ UserDictionary.Words.LOCALE + " is null";
private static final String DELETE_SELECTION = UserDictionary.Words.WORD + "=?";
+
+ private static final String EXTRA_WORD = "word";
private static final int CONTEXT_MENU_EDIT = Menu.FIRST;
private static final int CONTEXT_MENU_DELETE = Menu.FIRST + 1;
@@ -67,6 +71,9 @@ public class UserDictionarySettings extends ListActivity {
private Cursor mCursor;
+ private boolean mAddedWordAlready;
+ private boolean mAutoReturn;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -82,20 +89,34 @@ public class UserDictionarySettings extends ListActivity {
ListView listView = getListView();
listView.setFastScrollEnabled(true);
listView.setEmptyView(emptyView);
-
+
registerForContextMenu(listView);
}
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (!mAddedWordAlready
+ && getIntent().getAction().equals("com.android.settings.USER_DICTIONARY_INSERT")) {
+ String word = getIntent().getStringExtra(EXTRA_WORD);
+ mAutoReturn = true;
+ if (word != null) {
+ showAddOrEditDialog(word);
+ }
+ }
+ }
@Override
protected void onRestoreInstanceState(Bundle state) {
super.onRestoreInstanceState(state);
mDialogEditingWord = state.getString(INSTANCE_KEY_DIALOG_EDITING_WORD);
+ mAddedWordAlready = state.getBoolean(INSTANCE_KEY_ADDED_WORD, false);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(INSTANCE_KEY_DIALOG_EDITING_WORD, mDialogEditingWord);
+ outState.putBoolean(INSTANCE_KEY_ADDED_WORD, mAddedWordAlready);
}
private Cursor createCursor() {
@@ -115,7 +136,7 @@ public class UserDictionarySettings extends ListActivity {
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
- showAddOrEditDialog(getWord(position));
+ openContextMenu(v);
}
@Override
@@ -124,8 +145,10 @@ public class UserDictionarySettings extends ListActivity {
AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo;
menu.setHeaderTitle(getWord(adapterMenuInfo.position));
- menu.add(0, CONTEXT_MENU_EDIT, 0, R.string.user_dict_settings_context_menu_edit_title);
- menu.add(0, CONTEXT_MENU_DELETE, 0, R.string.user_dict_settings_context_menu_delete_title);
+ menu.add(0, CONTEXT_MENU_EDIT, 0,
+ R.string.user_dict_settings_context_menu_edit_title);
+ menu.add(0, CONTEXT_MENU_DELETE, 0,
+ R.string.user_dict_settings_context_menu_delete_title);
}
@Override
@@ -177,21 +200,32 @@ public class UserDictionarySettings extends ListActivity {
protected Dialog onCreateDialog(int id) {
View content = getLayoutInflater().inflate(R.layout.dialog_edittext, null);
final EditText editText = (EditText) content.findViewById(R.id.edittext);
+ // No prediction in soft keyboard mode. TODO: Create a better way to disable prediction
+ editText.setInputType(InputType.TYPE_CLASS_TEXT
+ | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
return new AlertDialog.Builder(this)
- .setTitle(R.string.user_dict_settings_add_dialog_title)
+ .setTitle(mDialogEditingWord != null
+ ? R.string.user_dict_settings_edit_dialog_title
+ : R.string.user_dict_settings_add_dialog_title)
.setView(content)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- onAddOrEditFinished(editText.getText().toString());
+ onAddOrEditFinished(editText.getText().toString());
+ if (mAutoReturn) finish();
+ }})
+ .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ if (mAutoReturn) finish();
}})
- .setNegativeButton(android.R.string.cancel, null)
.create();
}
-
@Override
protected void onPrepareDialog(int id, Dialog d) {
AlertDialog dialog = (AlertDialog) d;
+ d.setTitle(mDialogEditingWord != null
+ ? R.string.user_dict_settings_edit_dialog_title
+ : R.string.user_dict_settings_add_dialog_title);
EditText editText = (EditText) dialog.findViewById(R.id.edittext);
editText.setText(mDialogEditingWord);
}
@@ -207,8 +241,9 @@ public class UserDictionarySettings extends ListActivity {
// TODO: present UI for picking whether to add word to all locales, or current.
UserDictionary.Words.addWord(this, word.toString(),
- 1, UserDictionary.Words.LOCALE_TYPE_ALL);
+ 250, UserDictionary.Words.LOCALE_TYPE_ALL);
mCursor.requery();
+ mAddedWordAlready = true;
}
private void deleteWord(String word) {
diff --git a/src/com/android/settings/battery_history/BatteryHistory.java b/src/com/android/settings/battery_history/BatteryHistory.java
new file mode 100644
index 00000000000..dcf6cbf78b1
--- /dev/null
+++ b/src/com/android/settings/battery_history/BatteryHistory.java
@@ -0,0 +1,861 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.battery_history;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.settings.R;
+
+import android.app.Activity;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.BatteryStats.Timer;
+import android.os.BatteryStats.Uid;
+import android.util.Log;
+import android.util.LogPrinter;
+import android.util.SparseArray;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.AdapterView.OnItemSelectedListener;
+
+public class BatteryHistory extends Activity implements OnClickListener, OnItemSelectedListener {
+ private static final String TAG = "BatteryHistory";
+
+ private static final int SECONDS_PER_MINUTE = 60;
+ private static final int SECONDS_PER_HOUR = 60 * 60;
+ private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+
+ // Must be in sync with the values in res/values/array.xml (id battery_history_type_spinner)
+ private static final int CPU_USAGE = 0;
+ private static final int NETWORK_USAGE = 1;
+ private static final int GPS_USAGE = 2;
+ private static final int SENSOR_USAGE = 3;
+ private static final int WAKELOCK_USAGE = 4;
+ private static final int MISC_USAGE = 5;
+
+ // Must be in sync with the values in res/values/array.xml (id battery_history_which_spinner)
+ private static final int UNPLUGGED = 0;
+ private static final int CURRENT = 1;
+ private static final int TOTAL = 2;
+
+ private BatteryStats mStats;
+ private int mWhich = BatteryStats.STATS_UNPLUGGED;
+ private int mType = CPU_USAGE;
+
+ private GraphableButton[] mButtons;
+ IBatteryStats mBatteryInfo;
+
+ private List mCpuUsage = new ArrayList();
+ private List mNetworkUsage = new ArrayList();
+ private List mSensorUsage = new ArrayList();
+ private List mGpsUsage = new ArrayList();
+ private List mWakelockUsage = new ArrayList();
+ private List mMiscUsage = new ArrayList();
+
+ private boolean mHaveCpuUsage, mHaveNetworkUsage, mHaveSensorUsage,
+ mHaveWakelockUsage, mHaveMiscUsage;
+
+ private LinearLayout mGraphLayout;
+ private LinearLayout mTextLayout;
+ private TextView mMessageText;
+ private TextView mDetailsText;
+ private Button mDetailsBackButton;
+ private Spinner mTypeSpinner;
+ private Spinner mWhichSpinner;
+
+ private boolean mDetailsShown = false;
+
+ private static String getLabel(String packageName, PackageManager pm) {
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
+ CharSequence label = ai.loadLabel(pm);
+ if (label != null) {
+ return label.toString();
+ }
+ } catch (NameNotFoundException e) {
+ return packageName;
+ }
+
+ return "";
+ }
+
+ void formatTime(double millis, StringBuilder sb) {
+ int seconds = (int) Math.floor(millis / 1000);
+
+ int days = 0, hours = 0, minutes = 0;
+ if (seconds > SECONDS_PER_DAY) {
+ days = seconds / SECONDS_PER_DAY;
+ seconds -= days * SECONDS_PER_DAY;
+ }
+ if (seconds > SECONDS_PER_HOUR) {
+ hours = seconds / SECONDS_PER_HOUR;
+ seconds -= hours * SECONDS_PER_HOUR;
+ }
+ if (seconds > SECONDS_PER_MINUTE) {
+ minutes = seconds / SECONDS_PER_MINUTE;
+ seconds -= minutes * SECONDS_PER_MINUTE;
+ }
+ if (days > 0) {
+ sb.append(getString(R.string.battery_history_days, days, hours, minutes, seconds));
+ } else if (hours > 0) {
+ sb.append(getString(R.string.battery_history_hours, hours, minutes, seconds));
+ } else if (minutes > 0) {
+ sb.append(getString(R.string.battery_history_minutes, minutes, seconds));
+ } else {
+ sb.append(getString(R.string.battery_history_seconds, seconds));
+ }
+ }
+
+ abstract class Graphable implements Comparable {
+ protected String mName;
+ protected String mNamePackage;
+ protected boolean mUniqueName;
+ protected String[] mPackages;
+ protected String[] mPackageNames;
+
+ public abstract String getLabel();
+ public abstract double getSortValue();
+ public abstract double[] getValues();
+ public abstract void getInfo(StringBuilder info);
+
+ public double getMaxValue() {
+ return -Double.MAX_VALUE;
+ }
+
+ public int compareTo(Graphable o) {
+ double t = getSortValue();
+ double ot = o.getSortValue();
+ if (t < ot) {
+ // Largest first
+ return 1;
+ } else if (t > ot) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ // Side effects: sets mName and mUniqueName
+ void getNameForUid(int uid) {
+ PackageManager pm = getPackageManager();
+ mPackages = pm.getPackagesForUid(uid);
+ if (mPackages == null) {
+ mName = Integer.toString(uid);
+ mNamePackage = null;
+ return;
+ }
+
+ mPackageNames = new String[mPackages.length];
+ System.arraycopy(mPackages, 0, mPackageNames, 0, mPackages.length);
+
+ // Convert package names to user-facing labels where possible
+ for (int i = 0; i < mPackageNames.length; i++) {
+ mPackageNames[i] = BatteryHistory.getLabel(mPackageNames[i], pm);
+ }
+
+ if (mPackageNames.length == 1) {
+ mNamePackage = mPackages[0];
+ mName = mPackageNames[0];
+ mUniqueName = true;
+ } else {
+ mName = getString(R.string.battery_history_uid, uid); // Default name
+ // Look for an official name for this UID.
+ for (String name : mPackages) {
+ try {
+ PackageInfo pi = pm.getPackageInfo(name, 0);
+ if (pi.sharedUserLabel != 0) {
+ CharSequence nm = pm.getText(name,
+ pi.sharedUserLabel, pi.applicationInfo);
+ if (nm != null) {
+ mName = nm.toString();
+ break;
+ }
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ }
+ }
+ }
+ }
+
+ class CpuUsage extends Graphable {
+ String mProcess;
+ double[] mUsage;
+ double mTotalRuntime;
+ long mStarts;
+
+ public CpuUsage(int uid, String process, long userTime, long systemTime,
+ long starts, long totalRuntime) {
+ getNameForUid(uid);
+ mProcess = process;
+ PackageManager pm = BatteryHistory.this.getPackageManager();
+ mName = BatteryHistory.getLabel(process, pm);
+ mUsage = new double[2];
+
+ mUsage[0] = userTime;
+ mUsage[1] = userTime + systemTime;
+ mTotalRuntime = totalRuntime;
+ mStarts = starts;
+ }
+
+ public String getLabel() {
+ return mName;
+ }
+
+ public double getSortValue() {
+ return mUsage[1];
+ }
+
+ public double[] getValues() {
+ return mUsage;
+ }
+
+ public double getMaxValue() {
+ return mTotalRuntime;
+ }
+
+ public void getInfo(StringBuilder info) {
+ info.append(getString(R.string.battery_history_cpu_usage, mProcess));
+ info.append("\n\n");
+ info.append(getString(R.string.battery_history_user_time));
+ formatTime(mUsage[0] * 10, info);
+ info.append('\n');
+ info.append(getString(R.string.battery_history_system_time));
+ formatTime((mUsage[1] - mUsage[0]) * 10, info);
+ info.append('\n');
+ info.append(getString(R.string.battery_history_total_time));
+ formatTime((mUsage[1]) * 10, info);
+ info.append('\n');
+ info.append(getString(R.string.battery_history_starts, mStarts));
+ }
+ }
+
+ class NetworkUsage extends Graphable {
+ double[] mUsage;
+
+ public NetworkUsage(int uid, long received, long sent) {
+ getNameForUid(uid);
+
+ mUsage = new double[2];
+ mUsage[0] = received;
+ mUsage[1] = received + sent;
+ }
+
+ public String getLabel() {
+ return mName;
+ }
+
+ public double getSortValue() {
+ return mUsage[1];
+ }
+
+ public double[] getValues() {
+ return mUsage;
+ }
+
+ public void getInfo(StringBuilder info) {
+ info.append(getString(R.string.battery_history_network_usage, mName));
+ info.append("\n\n");
+ info.append(getString(R.string.battery_history_bytes_received, (long) mUsage[0]));
+ info.append('\n');
+ info.append(getString(R.string.battery_history_bytes_sent,
+ (long) mUsage[1] - (long) mUsage[0]));
+ info.append('\n');
+ info.append(getString(R.string.battery_history_bytes_total, (long) mUsage[1]));
+
+ if (!mUniqueName) {
+ info.append("\n\n");
+ info.append(getString(R.string.battery_history_packages_sharing_this_uid));
+ info.append('\n');
+
+ PackageManager pm = BatteryHistory.this.getPackageManager();
+ List names = new ArrayList();
+ for (String name : mPackageNames) {
+ names.add(BatteryHistory.getLabel(name, pm));
+ }
+ Collections.sort(names);
+ for (String name : names) {
+ info.append(" ");
+ info.append(name);
+ info.append('\n');
+ }
+ }
+ }
+ }
+
+ class SensorUsage extends Graphable {
+ double[] mUsage;
+ double mTotalRealtime;
+ int mCount;
+
+ public SensorUsage(int uid, long time, int count, long totalRealtime) {
+ getNameForUid(uid);
+
+ mUsage = new double[1];
+ mUsage[0] = time;
+ mTotalRealtime = totalRealtime;
+
+ mCount = count;
+ }
+
+ public String getLabel() {
+ return mName;
+ }
+
+ public double getSortValue() {
+ return mUsage[0];
+ }
+
+ public double[] getValues() {
+ return mUsage;
+ }
+
+ public double getMaxValue() {
+ return mTotalRealtime;
+ }
+
+ public void getInfo(StringBuilder info) {
+ info.append(getString(R.string.battery_history_sensor));
+ info.append(mName);
+ info.append("\n\n");
+ info.append(getString(R.string.battery_history_total_time));
+ formatTime(mUsage[0], info);
+ info.append("\n\n");
+ }
+ }
+
+
+ class WakelockUsage extends Graphable {
+ double[] mUsage;
+ double mTotalRealtime;
+ int mCount;
+
+ public WakelockUsage(int uid, long time, int count, long totalRealtime) {
+ getNameForUid(uid);
+
+ mUsage = new double[1];
+ mUsage[0] = time;
+ mTotalRealtime = totalRealtime;
+
+ mCount = count;
+ }
+
+ public String getLabel() {
+ return mName;
+ }
+
+ public double getSortValue() {
+ return mUsage[0];
+ }
+
+ public double[] getValues() {
+ return mUsage;
+ }
+
+ public double getMaxValue() {
+ return mTotalRealtime;
+ }
+
+ public void getInfo(StringBuilder info) {
+ info.append(getString(R.string.battery_history_wakelock));
+ info.append(mName);
+ info.append("\n\n");
+ info.append(getString(R.string.battery_history_total_time));
+ formatTime(mUsage[0], info);
+ info.append("\n\n");
+ }
+ }
+
+ class MiscUsage extends Graphable {
+ int mInfoLabelRes;
+ double[] mUsage;
+ double mTotalRealtime;
+
+ public MiscUsage(String name, int infoLabelRes, long value,
+ long totalRealtime) {
+ mName = name;
+
+ mInfoLabelRes = infoLabelRes;
+
+ mUsage = new double[2];
+ mUsage[0] = value;
+ mTotalRealtime = totalRealtime;
+ }
+
+ public String getLabel() {
+ return mName;
+ }
+
+ public double getSortValue() {
+ return mUsage[1];
+ }
+
+ public double[] getValues() {
+ return mUsage;
+ }
+
+ public double getMaxValue() {
+ return mTotalRealtime;
+ }
+
+ public void getInfo(StringBuilder info) {
+ info.append(getString(mInfoLabelRes));
+ info.append(' ');
+ formatTime(mUsage[0], info);
+ info.append(" (");
+ info.append((mUsage[0]*100)/mTotalRealtime);
+ info.append("%)");
+ }
+ }
+
+ private List extends Graphable> getGraphRecords() {
+ switch (mType) {
+ case CPU_USAGE: return mCpuUsage;
+ case NETWORK_USAGE : return mNetworkUsage;
+ case SENSOR_USAGE: return mSensorUsage;
+ case GPS_USAGE: return mGpsUsage;
+ case WAKELOCK_USAGE: return mWakelockUsage;
+ case MISC_USAGE: return mMiscUsage;
+ default:
+ return (List extends Graphable>) null; // TODO
+ }
+ }
+
+ private void displayGraph() {
+ Log.i(TAG, "displayGraph");
+
+ collectStatistics();
+
+ // Hide the UI and selectively enable it below
+ mMessageText.setVisibility(View.GONE);
+ for (int i = 0; i < mButtons.length; i++) {
+ mButtons[i].setVisibility(View.INVISIBLE);
+ }
+
+ double maxValue = -Double.MAX_VALUE;
+
+ List extends Graphable> records = getGraphRecords();
+ for (Graphable g : records) {
+ double[] values = g.getValues();
+ maxValue = Math.max(maxValue, values[values.length - 1]);
+ maxValue = Math.max(maxValue, g.getMaxValue());
+ }
+
+ int[] colors = new int[2];
+ colors[0] = 0xff0000ff;
+ colors[1] = 0xffff0000;
+
+ for (int i = 0; i < mButtons.length; i++) {
+ mButtons[i].setVisibility(View.INVISIBLE);
+ }
+
+ int numRecords = Math.min(records.size(), mButtons.length);
+ if (numRecords == 0) {
+ mMessageText.setVisibility(View.VISIBLE);
+ mMessageText.setText(R.string.battery_history_no_data);
+ } else {
+ for (int i = 0; i < numRecords; i++) {
+ Graphable r = records.get(i);
+
+ mButtons[i].setText(r.getLabel());
+ mButtons[i].setValues(r.getValues(), maxValue);
+ mButtons[i].setVisibility(View.VISIBLE);
+ }
+ }
+ }
+
+ private void hideDetails() {
+ mTextLayout.setVisibility(View.GONE);
+ mGraphLayout.setVisibility(View.VISIBLE);
+ mDetailsShown = false;
+ }
+
+ private void showDetails(int id) {
+ mGraphLayout.setVisibility(View.GONE);
+ mTextLayout.setVisibility(View.VISIBLE);
+
+ StringBuilder info = new StringBuilder();
+ List extends Graphable> records = getGraphRecords();
+ if (id < records.size()) {
+ Graphable record = records.get(id);
+ record.getInfo(info);
+ } else {
+ info.append(getString(R.string.battery_history_details_for, id));
+ }
+ mDetailsText.setText(info.toString());
+ mDetailsShown = true;
+ }
+
+ private void processCpuUsage() {
+ mCpuUsage.clear();
+
+ long uSecTime = SystemClock.uptimeMillis() * 1000;
+ final long uSecNow = mStats.computeBatteryUptime(uSecTime, mWhich) / 1000;
+
+ SparseArray extends Uid> uidStats = mStats.getUidStats();
+ final int NU = uidStats.size();
+ for (int iu = 0; iu < NU; iu++) {
+ Uid u = uidStats.valueAt(iu);
+
+ Map processStats = u.getProcessStats();
+ if (processStats.size() > 0) {
+ for (Map.Entry ent
+ : processStats.entrySet()) {
+
+ Uid.Proc ps = ent.getValue();
+ long userTime = ps.getUserTime(mWhich);
+ long systemTime = ps.getSystemTime(mWhich);
+ long starts = ps.getStarts(mWhich);
+
+ if (userTime != 0 || systemTime != 0) {
+ mCpuUsage.add(new CpuUsage(u.getUid(), ent.getKey(),
+ userTime, systemTime, starts, uSecNow));
+ }
+ }
+ }
+ }
+ Collections.sort(mCpuUsage);
+ }
+
+ private void processNetworkUsage() {
+ mNetworkUsage.clear();
+
+ SparseArray extends Uid> uidStats = mStats.getUidStats();
+ final int NU = uidStats.size();
+ for (int iu = 0; iu < NU; iu++) {
+ Uid u = uidStats.valueAt(iu);
+
+ long received = u.getTcpBytesReceived(mWhich);
+ long sent = u.getTcpBytesSent(mWhich);
+ if (received + sent > 0) {
+ mNetworkUsage.add(new NetworkUsage(u.getUid(), received, sent));
+ }
+ }
+ Collections.sort(mNetworkUsage);
+ }
+
+ private void processSensorUsage() {
+ mGpsUsage.clear();
+ mSensorUsage.clear();
+
+ long uSecTime = SystemClock.elapsedRealtime() * 1000;
+ final long uSecNow = mStats.computeBatteryRealtime(uSecTime, mWhich) / 1000;
+
+ SparseArray extends Uid> uidStats = mStats.getUidStats();
+ final int NU = uidStats.size();
+ for (int iu = 0; iu < NU; iu++) {
+ Uid u = uidStats.valueAt(iu);
+ int uid = u.getUid();
+
+ Map sensorStats = u.getSensorStats();
+ long timeGps = 0;
+ int countGps = 0;
+ long timeOther = 0;
+ int countOther = 0;
+ if (sensorStats.size() > 0) {
+ for (Map.Entry ent
+ : sensorStats.entrySet()) {
+
+ Uid.Sensor se = ent.getValue();
+ int handle = se.getHandle();
+ Timer timer = se.getSensorTime();
+ if (timer != null) {
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTime(uSecNow, mWhich) + 500) / 1000;
+ int count = timer.getCount(mWhich);
+ if (handle == BatteryStats.Uid.Sensor.GPS) {
+ timeGps += totalTime;
+ countGps += count;
+ } else {
+ timeOther += totalTime;
+ countOther += count;
+ }
+ }
+ }
+ }
+
+ if (timeGps > 0) {
+ mGpsUsage.add(new SensorUsage(uid, timeGps, countGps, uSecNow));
+ }
+ if (timeOther > 0) {
+ mSensorUsage.add(new SensorUsage(uid, timeOther, countOther, uSecNow));
+ }
+ }
+
+ Collections.sort(mGpsUsage);
+ Collections.sort(mSensorUsage);
+ }
+
+ private void processWakelockUsage() {
+ mWakelockUsage.clear();
+
+ long uSecTime = SystemClock.elapsedRealtime() * 1000;
+ final long uSecNow = mStats.computeBatteryRealtime(uSecTime, mWhich) / 1000;
+
+ SparseArray extends Uid> uidStats = mStats.getUidStats();
+ final int NU = uidStats.size();
+ for (int iu = 0; iu < NU; iu++) {
+ Uid u = uidStats.valueAt(iu);
+ int uid = u.getUid();
+
+ Map wakelockStats = u.getWakelockStats();
+ long time = 0;
+ int count = 0;
+ if (wakelockStats.size() > 0) {
+ for (Map.Entry ent
+ : wakelockStats.entrySet()) {
+
+ Uid.Wakelock wl = ent.getValue();
+ Timer timer = wl.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
+ if (timer != null) {
+ // Convert from microseconds to milliseconds with rounding
+ time += (timer.getTotalTime(uSecNow, mWhich) + 500) / 1000;
+ count += timer.getCount(mWhich);
+ }
+ }
+ }
+
+ if (time > 0) {
+ mWakelockUsage.add(new WakelockUsage(uid, time, count, uSecNow));
+ }
+ }
+
+ Collections.sort(mWakelockUsage);
+ }
+
+ private void processMiscUsage() {
+ mMiscUsage.clear();
+
+ long rawRealtime = SystemClock.elapsedRealtime() * 1000;
+ final long batteryRealtime = mStats.getBatteryRealtime(rawRealtime);
+ final long whichRealtime = mStats.computeBatteryRealtime(rawRealtime, mWhich) / 1000;
+
+ long time = mStats.computeBatteryUptime(SystemClock.uptimeMillis() * 1000, mWhich) / 1000;
+ if (time > 0) {
+ mMiscUsage.add(new MiscUsage(getString(
+ R.string.battery_history_awake_label),
+ R.string.battery_history_awake,
+ time, whichRealtime));
+ }
+
+ time = mStats.getScreenOnTime(batteryRealtime, mWhich) / 1000;
+ if (time > 0) {
+ mMiscUsage.add(new MiscUsage(getString(
+ R.string.battery_history_screen_on_label),
+ R.string.battery_history_screen_on,
+ time, whichRealtime));
+ }
+
+ time = mStats.getPhoneOnTime(batteryRealtime, mWhich) / 1000;
+ if (time > 0) {
+ mMiscUsage.add(new MiscUsage(getString(
+ R.string.battery_history_phone_on_label),
+ R.string.battery_history_phone_on,
+ time, whichRealtime));
+ }
+
+ Collections.sort(mMiscUsage);
+ }
+
+ private void collectStatistics() {
+ if (mType == CPU_USAGE) {
+ if (!mHaveCpuUsage) {
+ mHaveCpuUsage = true;
+ processCpuUsage();
+ }
+ }
+ if (mType == NETWORK_USAGE) {
+ if (!mHaveNetworkUsage) {
+ mHaveNetworkUsage = true;
+ processNetworkUsage();
+ }
+ }
+ if (mType == GPS_USAGE || mType == SENSOR_USAGE) {
+ if (!mHaveSensorUsage) {
+ mHaveSensorUsage = true;
+ processSensorUsage();
+ }
+ }
+ if (mType == WAKELOCK_USAGE) {
+ if (!mHaveWakelockUsage) {
+ mHaveWakelockUsage = true;
+ processWakelockUsage();
+ }
+ }
+ if (mType == MISC_USAGE) {
+ if (!mHaveMiscUsage) {
+ mHaveMiscUsage = true;
+ processMiscUsage();
+ }
+ }
+ }
+
+ private void load() {
+ try {
+ byte[] data = mBatteryInfo.getStatistics();
+ Parcel parcel = Parcel.obtain();
+ //Log.i(TAG, "Got data: " + data.length + " bytes");
+ parcel.unmarshall(data, 0, data.length);
+ parcel.setDataPosition(0);
+ mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
+ .createFromParcel(parcel);
+ //Log.i(TAG, "RECEIVED BATTERY INFO:");
+ //mStats.dumpLocked(new LogPrinter(Log.INFO, TAG));
+
+ mHaveCpuUsage = mHaveNetworkUsage = mHaveSensorUsage
+ = mHaveWakelockUsage = mHaveMiscUsage = false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException:", e);
+ }
+ }
+
+ public void onClick(View v) {
+ if (v == mDetailsBackButton) {
+ hideDetails();
+ return;
+ }
+
+ int id = ((Integer) v.getTag()).intValue();
+ showDetails(id);
+ }
+
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK && mDetailsShown) {
+ hideDetails();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ int oldWhich = mWhich;
+
+ if (parent.equals(mTypeSpinner)) {
+ mType = position;
+ } else if (parent.equals(mWhichSpinner)) {
+ switch (position) {
+ case UNPLUGGED:
+ mWhich = BatteryStats.STATS_UNPLUGGED;
+ break;
+ case CURRENT:
+ mWhich = BatteryStats.STATS_CURRENT;
+ break;
+ case TOTAL:
+ mWhich = BatteryStats.STATS_TOTAL;
+ break;
+ }
+ }
+
+ if (oldWhich != mWhich) {
+ mHaveCpuUsage = mHaveNetworkUsage = mHaveSensorUsage
+ = mHaveWakelockUsage = mHaveMiscUsage = false;
+ }
+
+ displayGraph();
+ }
+
+ public void onNothingSelected(AdapterView> parent) {
+ // Do nothing
+ }
+
+ @Override
+ public Object onRetainNonConfigurationInstance() {
+ BatteryStats stats = mStats;
+ mStats = null;
+ return stats;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (mStats != null) {
+ outState.putParcelable("stats", mStats);
+ }
+ outState.putInt("type", mType);
+ outState.putInt("which", mWhich);
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Log.i(TAG, "onCreate");
+
+ setContentView(R.layout.battery_history);
+
+ mGraphLayout = (LinearLayout) findViewById(R.id.graphLayout);
+ mTextLayout = (LinearLayout) findViewById(R.id.textLayout);
+ mDetailsText = (TextView) findViewById(R.id.detailsText);
+ mMessageText = (TextView) findViewById(R.id.messageText);
+
+ mTypeSpinner = (Spinner) findViewById(R.id.typeSpinner);
+ mTypeSpinner.setOnItemSelectedListener(this);
+
+ mWhichSpinner = (Spinner) findViewById(R.id.whichSpinner);
+ mWhichSpinner.setOnItemSelectedListener(this);
+ mWhichSpinner.setEnabled(true);
+
+ mButtons = new GraphableButton[8];
+ mButtons[0] = (GraphableButton) findViewById(R.id.button0);
+ mButtons[1] = (GraphableButton) findViewById(R.id.button1);
+ mButtons[2] = (GraphableButton) findViewById(R.id.button2);
+ mButtons[3] = (GraphableButton) findViewById(R.id.button3);
+ mButtons[4] = (GraphableButton) findViewById(R.id.button4);
+ mButtons[5] = (GraphableButton) findViewById(R.id.button5);
+ mButtons[6] = (GraphableButton) findViewById(R.id.button6);
+ mButtons[7] = (GraphableButton) findViewById(R.id.button7);
+
+ for (int i = 0; i < mButtons.length; i++) {
+ mButtons[i].setTag(i);
+ mButtons[i].setOnClickListener(this);
+ }
+
+ mBatteryInfo = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService("batteryinfo"));
+
+ mStats = (BatteryStats)getLastNonConfigurationInstance();
+ if (icicle != null) {
+ if (mStats == null) {
+ mStats = (BatteryStats)icicle.getParcelable("stats");
+ }
+ mType = icicle.getInt("type");
+ mWhich = icicle.getInt("which");
+ }
+ if (mStats == null) {
+ load();
+ }
+ displayGraph();
+ }
+}
diff --git a/src/com/android/settings/battery_history/GraphableButton.java b/src/com/android/settings/battery_history/GraphableButton.java
new file mode 100644
index 00000000000..39028d03638
--- /dev/null
+++ b/src/com/android/settings/battery_history/GraphableButton.java
@@ -0,0 +1,55 @@
+package com.android.settings.battery_history;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.Button;
+
+public class GraphableButton extends Button {
+ private static final String TAG = "GraphableButton";
+
+ static Paint[] sPaint = new Paint[2];
+ static {
+ sPaint[0] = new Paint();
+ sPaint[0].setStyle(Paint.Style.FILL);
+ sPaint[0].setColor(Color.BLUE);
+
+ sPaint[1] = new Paint();
+ sPaint[1].setStyle(Paint.Style.FILL);
+ sPaint[1].setColor(Color.RED);
+ }
+
+ double[] mValues;
+
+ public GraphableButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setValues(double[] values, double maxValue) {
+ mValues = values.clone();
+ for (int i = 0; i < values.length; i++) {
+ mValues[i] /= maxValue;
+ }
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ Log.i(TAG, "onDraw: w = " + getWidth() + ", h = " + getHeight());
+
+ int xmin = getPaddingLeft();
+ int xmax = getWidth() - getPaddingRight();
+ int ymin = getPaddingTop();
+ int ymax = getHeight() - getPaddingBottom();
+
+ int startx = xmin;
+ for (int i = 0; i < mValues.length; i++) {
+ int endx = xmin + (int) (mValues[i] * (xmax - xmin));
+ canvas.drawRect(startx, ymin, endx, ymax, sPaint[i]);
+ startx = endx;
+ }
+ super.onDraw(canvas);
+ }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
index facb76397bb..f1a2a1e409d 100644
--- a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
+++ b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
@@ -19,6 +19,7 @@ package com.android.settings.bluetooth;
import com.android.settings.R;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothError;
import android.bluetooth.BluetoothIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -56,14 +57,12 @@ public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChan
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- /*
- * TODO: remove this once the BT framework broadcasts the
- * MODE_CHANGED action when going into MODE_OFF.
- */
- int mode = BluetoothIntent.DISABLED_ACTION.equals(intent.getAction())
- ? BluetoothDevice.MODE_OFF
- : intent.getIntExtra(BluetoothIntent.MODE, BluetoothDevice.MODE_UNKNOWN);
- handleModeChanged(mode);
+ if (BluetoothIntent.SCAN_MODE_CHANGED_ACTION.equals(intent.getAction())) {
+ int mode = intent.getIntExtra(BluetoothIntent.SCAN_MODE, BluetoothError.ERROR);
+ if (mode != BluetoothError.ERROR) {
+ handleModeChanged(mode);
+ }
+ }
}
};
@@ -92,12 +91,12 @@ public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChan
return;
}
- IntentFilter filter = new IntentFilter(BluetoothIntent.MODE_CHANGED_ACTION);
+ IntentFilter filter = new IntentFilter(BluetoothIntent.SCAN_MODE_CHANGED_ACTION);
filter.addAction(BluetoothIntent.DISABLED_ACTION);
mContext.registerReceiver(mReceiver, filter);
mCheckBoxPreference.setOnPreferenceChangeListener(this);
- handleModeChanged(mLocalManager.getBluetoothManager().getMode());
+ handleModeChanged(mLocalManager.getBluetoothManager().getScanMode());
}
public void pause() {
@@ -128,15 +127,16 @@ public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChan
int timeout = getDiscoverableTimeout();
manager.setDiscoverableTimeout(timeout);
-
+
+ mCheckBoxPreference.setSummaryOn(
+ mContext.getResources().getString(R.string.bluetooth_is_discoverable, timeout));
+
long endTimestamp = System.currentTimeMillis() + timeout * 1000;
persistDiscoverableEndTimestamp(endTimestamp);
- manager.setMode(BluetoothDevice.MODE_DISCOVERABLE);
- handleModeChanged(BluetoothDevice.MODE_DISCOVERABLE);
-
+ manager.setScanMode(BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
} else {
- manager.setMode(BluetoothDevice.MODE_CONNECTABLE);
+ manager.setScanMode(BluetoothDevice.SCAN_MODE_CONNECTABLE);
}
}
@@ -160,7 +160,7 @@ public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChan
Log.v(TAG, "Got mode changed: " + mode);
}
- if (mode == BluetoothDevice.MODE_DISCOVERABLE) {
+ if (mode == BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
mCheckBoxPreference.setChecked(true);
updateCountdownSummary();
@@ -170,8 +170,8 @@ public class BluetoothDiscoverableEnabler implements Preference.OnPreferenceChan
}
private void updateCountdownSummary() {
- int mode = mLocalManager.getBluetoothManager().getMode();
- if (mode != BluetoothDevice.MODE_DISCOVERABLE) {
+ int mode = mLocalManager.getBluetoothManager().getScanMode();
+ if (mode != BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
return;
}
diff --git a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
index fe64d130bd4..2ad5726ddc7 100644
--- a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
+++ b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
@@ -52,31 +52,39 @@ public class BluetoothEventRedirector {
if (action.equals(BluetoothIntent.ENABLED_ACTION)) {
mManager.setBluetoothStateInt(ExtendedBluetoothState.ENABLED);
+
} else if (action.equals(BluetoothIntent.DISABLED_ACTION)) {
mManager.setBluetoothStateInt(ExtendedBluetoothState.DISABLED);
} else if (action.equals(BluetoothIntent.DISCOVERY_STARTED_ACTION)) {
mManager.onScanningStateChanged(true);
+
} else if (action.equals(BluetoothIntent.DISCOVERY_COMPLETED_ACTION)) {
mManager.onScanningStateChanged(false);
} else if (action.equals(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION)) {
short rssi = intent.getShortExtra(BluetoothIntent.RSSI, Short.MIN_VALUE);
mManager.getLocalDeviceManager().onDeviceAppeared(address, rssi);
+
} else if (action.equals(BluetoothIntent.REMOTE_DEVICE_DISAPPEARED_ACTION)) {
mManager.getLocalDeviceManager().onDeviceDisappeared(address);
+
} else if (action.equals(BluetoothIntent.REMOTE_NAME_UPDATED_ACTION)) {
mManager.getLocalDeviceManager().onDeviceNameUpdated(address);
+
} else if (action.equals(BluetoothIntent.BOND_STATE_CHANGED_ACTION)) {
int bondState = intent.getIntExtra(BluetoothIntent.BOND_STATE,
BluetoothError.ERROR);
mManager.getLocalDeviceManager().onBondingStateChanged(address, bondState);
if (bondState == BluetoothDevice.BOND_NOT_BONDED) {
int reason = intent.getIntExtra(BluetoothIntent.REASON, BluetoothError.ERROR);
- Log.w(TAG, address + " unbonded with reason " + reason +
- ", TODO: handle this nicely in the UI"); //TODO
- mManager.getLocalDeviceManager().onBondingError(address);
+ if (reason == BluetoothDevice.UNBOND_REASON_AUTH_FAILED ||
+ reason == BluetoothDevice.UNBOND_REASON_AUTH_REJECTED ||
+ reason == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN) {
+ mManager.getLocalDeviceManager().onBondingError(address, reason);
+ }
}
+
} else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) {
mManager.getLocalDeviceManager().onProfileStateChanged(address);
@@ -84,7 +92,7 @@ public class BluetoothEventRedirector {
int oldState = intent.getIntExtra(BluetoothIntent.HEADSET_PREVIOUS_STATE, 0);
if (newState == BluetoothHeadset.STATE_DISCONNECTED &&
oldState == BluetoothHeadset.STATE_CONNECTING) {
- mManager.getLocalDeviceManager().onConnectingError(address);
+ Log.i(TAG, "Failed to connect BT headset");
}
} else if (action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
@@ -94,8 +102,12 @@ public class BluetoothEventRedirector {
int oldState = intent.getIntExtra(BluetoothA2dp.SINK_PREVIOUS_STATE, 0);
if (newState == BluetoothA2dp.STATE_DISCONNECTED &&
oldState == BluetoothA2dp.STATE_CONNECTING) {
- mManager.getLocalDeviceManager().onConnectingError(address);
+ Log.i(TAG, "Failed to connect BT A2DP");
}
+
+ } else if (action.equals(BluetoothIntent.REMOTE_DEVICE_CLASS_UPDATED_ACTION)) {
+ mManager.getLocalDeviceManager().onBtClassChanged(address);
+
}
}
};
@@ -124,6 +136,7 @@ public class BluetoothEventRedirector {
// Fine-grained state broadcasts
filter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
filter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION);
+ filter.addAction(BluetoothIntent.REMOTE_DEVICE_CLASS_UPDATED_ACTION);
mManager.getContext().registerReceiver(mBroadcastReceiver, filter);
}
diff --git a/src/com/android/settings/bluetooth/BluetoothPinDialog.java b/src/com/android/settings/bluetooth/BluetoothPinDialog.java
index 291d0c15cae..087fbb291c6 100644
--- a/src/com/android/settings/bluetooth/BluetoothPinDialog.java
+++ b/src/com/android/settings/bluetooth/BluetoothPinDialog.java
@@ -18,13 +18,19 @@ package com.android.settings.bluetooth;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentFilter;
import android.os.Bundle;
+import android.text.Editable;
import android.text.InputFilter;
-import android.text.method.DigitsKeyListener;
+import android.text.TextWatcher;
+import android.text.InputFilter.LengthFilter;
import android.util.Log;
import android.view.View;
+import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
@@ -36,12 +42,32 @@ import com.android.settings.R;
* BluetoothPinDialog asks the user to enter a PIN for pairing with a remote
* Bluetooth device. It is an activity that appears as a dialog.
*/
-public class BluetoothPinDialog extends AlertActivity implements DialogInterface.OnClickListener {
+public class BluetoothPinDialog extends AlertActivity implements DialogInterface.OnClickListener,
+ TextWatcher {
private static final String TAG = "BluetoothPinDialog";
+ private final int BLUETOOTH_PIN_MAX_LENGTH = 16;
private LocalBluetoothManager mLocalManager;
private String mAddress;
private EditText mPinView;
+ private Button mOkButton;
+
+ private static final String INSTANCE_KEY_PAIRING_CANCELED = "received_pairing_canceled";
+ private boolean mReceivedPairingCanceled;
+
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!BluetoothIntent.PAIRING_CANCEL_ACTION.equals(intent.getAction())) {
+ return;
+ }
+
+ String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
+ if (address == null || address.equals(mAddress)) {
+ onReceivedPairingCanceled();
+ }
+ }
+ };
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -69,6 +95,39 @@ public class BluetoothPinDialog extends AlertActivity implements DialogInterface
p.mNegativeButtonText = getString(android.R.string.cancel);
p.mNegativeButtonListener = this;
setupAlert();
+
+ mOkButton = mAlert.getButton(DialogInterface.BUTTON_POSITIVE);
+ mOkButton.setEnabled(false);
+
+ /*
+ * Leave this registered through pause/resume since we still want to
+ * finish the activity in the background if pairing is canceled.
+ */
+ registerReceiver(mReceiver, new IntentFilter(BluetoothIntent.PAIRING_CANCEL_ACTION));
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+
+ mReceivedPairingCanceled = savedInstanceState.getBoolean(INSTANCE_KEY_PAIRING_CANCELED);
+ if (mReceivedPairingCanceled) {
+ onReceivedPairingCanceled();
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ outState.putBoolean(INSTANCE_KEY_PAIRING_CANCELED, mReceivedPairingCanceled);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ unregisterReceiver(mReceiver);
}
private View createView() {
@@ -79,9 +138,33 @@ public class BluetoothPinDialog extends AlertActivity implements DialogInterface
messageView.setText(getString(R.string.bluetooth_enter_pin_msg, name));
mPinView = (EditText) view.findViewById(R.id.text);
+ mPinView.addTextChangedListener(this);
+ // Maximum of 16 characters in a PIN
+ mPinView.setFilters(new InputFilter[] { new LengthFilter(BLUETOOTH_PIN_MAX_LENGTH) });
return view;
}
+
+ public void afterTextChanged(Editable s) {
+ if (s.length() > 0) {
+ mOkButton.setEnabled(true);
+ }
+ }
+
+ private void onReceivedPairingCanceled() {
+ mReceivedPairingCanceled = true;
+
+ TextView messageView = (TextView) findViewById(R.id.message);
+ messageView.setText(getString(R.string.bluetooth_pairing_error_message,
+ mLocalManager.getLocalDeviceManager().getName(mAddress)));
+
+ mPinView.setVisibility(View.GONE);
+ mPinView.clearFocus();
+ mPinView.removeTextChangedListener(this);
+
+ mOkButton.setEnabled(true);
+ mAlert.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.GONE);
+ }
private void onPair(String pin) {
byte[] pinBytes = BluetoothDevice.convertPinToBytes(pin);
@@ -94,7 +177,7 @@ public class BluetoothPinDialog extends AlertActivity implements DialogInterface
}
private void onCancel() {
- mLocalManager.getBluetoothManager().cancelPin(mAddress);
+ mLocalManager.getBluetoothManager().cancelBondProcess(mAddress);
}
public void onClick(DialogInterface dialog, int which) {
@@ -109,4 +192,12 @@ public class BluetoothPinDialog extends AlertActivity implements DialogInterface
}
}
+ /* Not used */
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ /* Not used */
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
}
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index f75e5f5d0c7..5adada3c424 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -253,6 +253,8 @@ public class BluetoothSettings extends PreferenceActivity
// we should start a scan
if (bluetoothState == ExtendedBluetoothState.ENABLED) {
mLocalManager.startScanning(false);
+ } else if (bluetoothState == ExtendedBluetoothState.DISABLED) {
+ mDeviceList.setProgress(false);
}
}
}
diff --git a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
index 23a43bd9d13..7dd1b706d7b 100644
--- a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
+++ b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
@@ -25,10 +25,7 @@ import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
-import android.preference.PreferenceScreen;
import android.text.TextUtils;
-import android.widget.ImageView;
-import android.widget.TextView;
import android.util.Log;
/**
@@ -114,7 +111,7 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
mManager.setForegroundActivity(this);
mDevice.registerCallback(this);
- refresh(true);
+ refresh();
}
@Override
@@ -169,7 +166,7 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
}
private void onOnlineModeCheckedStateChanged(boolean checked) {
- switchModes(checked, false);
+ setOnlineMode(checked, true);
}
private void onProfileCheckedStateChanged(Profile profile, boolean checked) {
@@ -187,44 +184,42 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
}
public void onDeviceAttributesChanged(LocalBluetoothDevice device) {
- refresh(false);
+ refresh();
}
- private void refresh(boolean forceRefresh) {
- // The online mode could have changed
- updateOnlineMode(forceRefresh);
+ private void refresh() {
+ // We are in 'online mode' if we are connected, connecting, or disconnecting
+ setOnlineMode(mDevice.isConnected() || mDevice.isBusy(), false);
refreshProfiles();
- refreshOnlineModePreference();
}
- private void updateOnlineMode(boolean force) {
- // Connected or Connecting (and Disconnecting, which is fine)
- boolean onlineMode = mDevice.isConnected() || mDevice.isBusy();
- switchModes(onlineMode, force);
- }
-
/**
* Switches between online/offline mode.
*
* @param onlineMode Whether to be in online mode, or offline mode.
+ * @param takeAction Whether to take action (i.e., connect or disconnect)
+ * based on the new online mode.
*/
- private void switchModes(boolean onlineMode, boolean force) {
- if (mOnlineMode != onlineMode || force) {
- mOnlineMode = onlineMode;
+ private void setOnlineMode(boolean onlineMode, boolean takeAction) {
+ mOnlineMode = onlineMode;
+ if (takeAction) {
if (onlineMode) {
mDevice.connect();
} else {
mDevice.disconnect();
}
-
- refreshOnlineModePreference();
}
+
+ refreshOnlineModePreference();
}
private void refreshOnlineModePreference() {
mOnlineModePreference.setChecked(mOnlineMode);
+ /* Gray out checkbox while connecting and disconnecting */
+ mOnlineModePreference.setEnabled(!mDevice.isBusy());
+
/**
* If the device is online, show status. Otherwise, show a summary that
* describes what the checkbox does.
@@ -237,9 +232,12 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
for (Profile profile : mDevice.getProfiles()) {
CheckBoxPreference profilePref =
(CheckBoxPreference) findPreference(profile.toString());
- if (profilePref == null) continue;
-
- refreshProfilePreference(profilePref, profile);
+ if (profilePref == null) {
+ profilePref = createProfilePreference(profile);
+ mProfileContainer.addPreference(profilePref);
+ } else {
+ refreshProfilePreference(profilePref, profile);
+ }
}
}
@@ -249,7 +247,10 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
.getProfileManager(mManager, profile);
int connectionStatus = profileManager.getConnectionStatus(address);
-
+
+ /* Gray out checkbox while connecting and disconnecting */
+ profilePref.setEnabled(!mDevice.isBusy());
+
profilePref.setSummary(getProfileSummary(profileManager, profile, address,
connectionStatus, mOnlineMode));
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothDevice.java b/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
index 26ddbf2e643..a4885401e23 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothDevice.java
@@ -30,6 +30,7 @@ import android.content.res.Resources;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
+import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuItem;
@@ -45,25 +46,23 @@ import java.util.List;
*/
public class LocalBluetoothDevice implements Comparable {
private static final String TAG = "LocalBluetoothDevice";
-
+
private static final int CONTEXT_ITEM_CONNECT = Menu.FIRST + 1;
private static final int CONTEXT_ITEM_DISCONNECT = Menu.FIRST + 2;
private static final int CONTEXT_ITEM_UNPAIR = Menu.FIRST + 3;
private static final int CONTEXT_ITEM_CONNECT_ADVANCED = Menu.FIRST + 4;
-
+
private final String mAddress;
private String mName;
private short mRssi;
private int mBtClass = BluetoothClass.ERROR;
-
+
private List mProfiles = new ArrayList();
-
+
private boolean mVisible;
-
- private int mBondState;
-
+
private final LocalBluetoothManager mLocalManager;
-
+
private List mCallbacks = new ArrayList();
/**
@@ -71,22 +70,22 @@ public class LocalBluetoothDevice implements Comparable {
* error even if they all fail. This tracks that state.
*/
private boolean mIsConnectingErrorPossible;
-
+
LocalBluetoothDevice(Context context, String address) {
mLocalManager = LocalBluetoothManager.getInstance(context);
if (mLocalManager == null) {
throw new IllegalStateException(
"Cannot use LocalBluetoothDevice without Bluetooth hardware");
}
-
+
mAddress = address;
-
+
fillData();
}
-
+
public void onClicked() {
int bondState = getBondState();
-
+
if (isConnected()) {
askDisconnect();
} else if (bondState == BluetoothDevice.BOND_BONDED) {
@@ -95,22 +94,22 @@ public class LocalBluetoothDevice implements Comparable {
pair();
}
}
-
+
public void disconnect() {
for (Profile profile : mProfiles) {
disconnect(profile);
}
}
-
+
public void disconnect(Profile profile) {
LocalBluetoothProfileManager profileManager =
- LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
+ LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
int status = profileManager.getConnectionStatus(mAddress);
if (SettingsBtStatus.isConnectionStatusConnected(status)) {
profileManager.disconnect(mAddress);
}
}
-
+
public void askDisconnect() {
Context context = mLocalManager.getForegroundActivity();
if (context == null) {
@@ -118,21 +117,21 @@ public class LocalBluetoothDevice implements Comparable {
disconnect();
return;
}
-
+
Resources res = context.getResources();
-
+
String name = getName();
if (TextUtils.isEmpty(name)) {
name = res.getString(R.string.bluetooth_device);
}
String message = res.getString(R.string.bluetooth_disconnect_blank, name);
-
+
DialogInterface.OnClickListener disconnectListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
disconnect();
}
};
-
+
AlertDialog ad = new AlertDialog.Builder(context)
.setTitle(getName())
.setMessage(message)
@@ -140,10 +139,13 @@ public class LocalBluetoothDevice implements Comparable {
.setNegativeButton(android.R.string.cancel, null)
.show();
}
-
+
public void connect() {
if (!ensurePaired()) return;
-
+
+ // Reset the only-show-one-error-dialog tracking variable
+ mIsConnectingErrorPossible = true;
+
Context context = mLocalManager.getContext();
boolean hasAtLeastOnePreferredProfile = false;
for (Profile profile : mProfiles) {
@@ -151,49 +153,57 @@ public class LocalBluetoothDevice implements Comparable {
LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
if (profileManager.isPreferred(mAddress)) {
hasAtLeastOnePreferredProfile = true;
- connect(profile);
+ connectInt(profile);
}
}
-
+
if (!hasAtLeastOnePreferredProfile) {
connectAndPreferAllProfiles();
}
}
-
+
private void connectAndPreferAllProfiles() {
if (!ensurePaired()) return;
-
+
+ // Reset the only-show-one-error-dialog tracking variable
+ mIsConnectingErrorPossible = true;
+
Context context = mLocalManager.getContext();
for (Profile profile : mProfiles) {
LocalBluetoothProfileManager profileManager =
LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
profileManager.setPreferred(mAddress, true);
- connect(profile);
+ connectInt(profile);
}
}
-
+
public void connect(Profile profile) {
+ // Reset the only-show-one-error-dialog tracking variable
+ mIsConnectingErrorPossible = true;
+ connectInt(profile);
+ }
+
+ public void connectInt(Profile profile) {
if (!ensurePaired()) return;
-
+
LocalBluetoothProfileManager profileManager =
- LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
+ LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile);
int status = profileManager.getConnectionStatus(mAddress);
if (!SettingsBtStatus.isConnectionStatusConnected(status)) {
- mIsConnectingErrorPossible = true;
if (profileManager.connect(mAddress) != BluetoothDevice.RESULT_SUCCESS) {
- showConnectingError();
+ Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName);
}
}
}
-
+
public void showConnectingError() {
if (!mIsConnectingErrorPossible) return;
mIsConnectingErrorPossible = false;
-
+
mLocalManager.showError(mAddress, R.string.bluetooth_error_title,
R.string.bluetooth_connecting_error_message);
}
-
+
private boolean ensurePaired() {
if (getBondState() == BluetoothDevice.BOND_NOT_BONDED) {
pair();
@@ -211,9 +221,9 @@ public class LocalBluetoothDevice implements Comparable {
manager.cancelDiscovery();
}
- if (mLocalManager.createBonding(mAddress)) {
- //TODO: consider removing this line - UI will update through Intent
- setBondState(BluetoothDevice.BOND_BONDING);
+ if (!mLocalManager.getBluetoothManager().createBond(mAddress)) {
+ mLocalManager.showError(mAddress, R.string.bluetooth_error_title,
+ R.string.bluetooth_pairing_error_message);
}
}
@@ -235,17 +245,13 @@ public class LocalBluetoothDevice implements Comparable {
BluetoothDevice manager = mLocalManager.getBluetoothManager();
fetchName();
- mBtClass = manager.getRemoteClass(mAddress);
-
- LocalBluetoothProfileManager.fill(mBtClass, mProfiles);
-
- mBondState = manager.getBondState(mAddress);
+ fetchBtClass();
mVisible = false;
dispatchAttributesChanged();
}
-
+
public String getAddress() {
return mAddress;
}
@@ -253,20 +259,20 @@ public class LocalBluetoothDevice implements Comparable {
public String getName() {
return mName;
}
-
+
public void refreshName() {
fetchName();
dispatchAttributesChanged();
}
-
+
private void fetchName() {
mName = mLocalManager.getBluetoothManager().getRemoteName(mAddress);
-
+
if (TextUtils.isEmpty(mName)) {
mName = mAddress;
}
}
-
+
public void refresh() {
dispatchAttributesChanged();
}
@@ -283,14 +289,7 @@ public class LocalBluetoothDevice implements Comparable {
}
public int getBondState() {
- return mBondState;
- }
-
- void setBondState(int bondState) {
- if (mBondState != bondState) {
- mBondState = bondState;
- dispatchAttributesChanged();
- }
+ return mLocalManager.getBluetoothManager().getBondState(mAddress);
}
void setRssi(short rssi) {
@@ -299,10 +298,10 @@ public class LocalBluetoothDevice implements Comparable {
dispatchAttributesChanged();
}
}
-
+
/**
* Checks whether we are connected to this device (any profile counts).
- *
+ *
* @return Whether it is connected.
*/
public boolean isConnected() {
@@ -313,26 +312,26 @@ public class LocalBluetoothDevice implements Comparable {
return true;
}
}
-
+
return false;
}
-
+
public boolean isBusy() {
for (Profile profile : mProfiles) {
int status = LocalBluetoothProfileManager.getProfileManager(mLocalManager, profile)
- .getConnectionStatus(mAddress);
+ .getConnectionStatus(mAddress);
if (SettingsBtStatus.isConnectionStatusBusy(status)) {
return true;
}
}
-
+
if (getBondState() == BluetoothDevice.BOND_BONDING) {
return true;
}
-
+
return false;
}
-
+
public int getBtClassDrawable() {
// First try looking at profiles
@@ -341,7 +340,7 @@ public class LocalBluetoothDevice implements Comparable {
} else if (mProfiles.contains(Profile.HEADSET)) {
return R.drawable.ic_bt_headset_hfp;
}
-
+
// Fallback on class
switch (BluetoothClass.Device.Major.getDeviceMajor(mBtClass)) {
case BluetoothClass.Device.Major.COMPUTER:
@@ -349,24 +348,42 @@ public class LocalBluetoothDevice implements Comparable {
case BluetoothClass.Device.Major.PHONE:
return R.drawable.ic_bt_cellphone;
-
+
default:
return 0;
}
}
+ /**
+ * Fetches a new value for the cached BT class.
+ */
+ private void fetchBtClass() {
+ mBtClass = mLocalManager.getBluetoothManager().getRemoteClass(mAddress);
+ mProfiles.clear();
+ LocalBluetoothProfileManager.fill(mBtClass, mProfiles);
+ }
+
+ /**
+ * Refreshes the UI for the BT class, including fetching the latest value
+ * for the class.
+ */
+ public void refreshBtClass() {
+ fetchBtClass();
+ dispatchAttributesChanged();
+ }
+
public int getSummary() {
// TODO: clean up
int oneOffSummary = getOneOffSummary();
if (oneOffSummary != 0) {
return oneOffSummary;
}
-
+
for (Profile profile : mProfiles) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, profile);
int connectionStatus = profileManager.getConnectionStatus(mAddress);
-
+
if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus) ||
connectionStatus == SettingsBtStatus.CONNECTION_STATUS_CONNECTING ||
connectionStatus == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING) {
@@ -380,17 +397,17 @@ public class LocalBluetoothDevice implements Comparable {
/**
* We have special summaries when particular profiles are connected. This
* checks for those states and returns an applicable summary.
- *
- * @return A one-off summary that is applicable for the current state, or 0.
+ *
+ * @return A one-off summary that is applicable for the current state, or 0.
*/
private int getOneOffSummary() {
boolean isA2dpConnected = false, isHeadsetConnected = false, isConnecting = false;
-
+
if (mProfiles.contains(Profile.A2DP)) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, Profile.A2DP);
isConnecting = profileManager.getConnectionStatus(mAddress) ==
- SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
+ SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
isA2dpConnected = profileManager.isConnected(mAddress);
}
@@ -398,10 +415,10 @@ public class LocalBluetoothDevice implements Comparable {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
.getProfileManager(mLocalManager, Profile.HEADSET);
isConnecting |= profileManager.getConnectionStatus(mAddress) ==
- SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
+ SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
isHeadsetConnected = profileManager.isConnected(mAddress);
}
-
+
if (isConnecting) {
// If any of these important profiles is connecting, prefer that
return SettingsBtStatus.getConnectionStatusSummary(
@@ -416,7 +433,7 @@ public class LocalBluetoothDevice implements Comparable {
return 0;
}
}
-
+
public List getProfiles() {
return new ArrayList(mProfiles);
}
@@ -424,25 +441,23 @@ public class LocalBluetoothDevice implements Comparable {
public void onCreateContextMenu(ContextMenu menu) {
// No context menu if it is busy (none of these items are applicable if busy)
if (isBusy()) return;
-
- // No context menu if there are no profiles
- if (mProfiles.size() == 0) return;
-
+
int bondState = getBondState();
boolean isConnected = isConnected();
-
+ boolean hasProfiles = mProfiles.size() > 0;
+
menu.setHeaderTitle(getName());
-
+
if (isConnected) {
menu.add(0, CONTEXT_ITEM_DISCONNECT, 0, R.string.bluetooth_device_context_disconnect);
- } else {
+ } else if (hasProfiles) {
// For connection action, show either "Connect" or "Pair & connect"
int connectString = (bondState == BluetoothDevice.BOND_NOT_BONDED)
? R.string.bluetooth_device_context_pair_connect
: R.string.bluetooth_device_context_connect;
menu.add(0, CONTEXT_ITEM_CONNECT, 0, connectString);
}
-
+
if (bondState == BluetoothDevice.BOND_BONDED) {
// For unpair action, show either "Unpair" or "Disconnect & unpair"
int unpairString = isConnected
@@ -458,7 +473,7 @@ public class LocalBluetoothDevice implements Comparable {
/**
* Called when a context menu item is clicked.
- *
+ *
* @param item The item that was clicked.
*/
public void onContextItemSelected(MenuItem item) {
@@ -466,15 +481,16 @@ public class LocalBluetoothDevice implements Comparable {
case CONTEXT_ITEM_DISCONNECT:
disconnect();
break;
-
+
case CONTEXT_ITEM_CONNECT:
connect();
break;
-
+
case CONTEXT_ITEM_UNPAIR:
+ mLocalManager.getBluetoothManager().disconnectRemoteDeviceAcl(mAddress);
unpair();
break;
-
+
case CONTEXT_ITEM_CONNECT_ADVANCED:
Intent intent = new Intent();
// Need an activity context to open this in our task
@@ -496,13 +512,13 @@ public class LocalBluetoothDevice implements Comparable {
mCallbacks.add(callback);
}
}
-
+
public void unregisterCallback(Callback callback) {
synchronized (mCallbacks) {
mCallbacks.remove(callback);
}
}
-
+
private void dispatchAttributesChanged() {
synchronized (mCallbacks) {
for (Callback callback : mCallbacks) {
@@ -510,7 +526,7 @@ public class LocalBluetoothDevice implements Comparable {
}
}
}
-
+
@Override
public String toString() {
return mAddress;
@@ -521,7 +537,7 @@ public class LocalBluetoothDevice implements Comparable {
if ((o == null) || !(o instanceof LocalBluetoothDevice)) {
throw new ClassCastException();
}
-
+
return mAddress.equals(((LocalBluetoothDevice) o).mAddress);
}
@@ -529,27 +545,27 @@ public class LocalBluetoothDevice implements Comparable {
public int hashCode() {
return mAddress.hashCode();
}
-
+
public int compareTo(LocalBluetoothDevice another) {
- int comparison;
-
+ int comparison;
+
// Connected above not connected
comparison = (another.isConnected() ? 1 : 0) - (isConnected() ? 1 : 0);
if (comparison != 0) return comparison;
-
+
// Paired above not paired
- comparison = (another.mBondState == BluetoothDevice.BOND_BONDED ? 1 : 0) -
- (mBondState == BluetoothDevice.BOND_BONDED ? 1 : 0);
+ comparison = (another.getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0) -
+ (getBondState() == BluetoothDevice.BOND_BONDED ? 1 : 0);
if (comparison != 0) return comparison;
// Visible above not visible
comparison = (another.mVisible ? 1 : 0) - (mVisible ? 1 : 0);
if (comparison != 0) return comparison;
-
+
// Stronger signal above weaker signal
comparison = another.mRssi - mRssi;
if (comparison != 0) return comparison;
-
+
// Fallback on name
return getName().compareTo(another.getName());
}
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java b/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java
index a751656df72..6bb2b4afe16 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothDeviceManager.java
@@ -45,19 +45,23 @@ public class LocalBluetoothDeviceManager {
readPairedDevices();
}
- private synchronized void readPairedDevices() {
+ private synchronized boolean readPairedDevices() {
BluetoothDevice manager = mLocalManager.getBluetoothManager();
String[] bondedAddresses = manager.listBonds();
- if (bondedAddresses == null) return;
+ if (bondedAddresses == null) return false;
+ boolean deviceAdded = false;
for (String address : bondedAddresses) {
LocalBluetoothDevice device = findDevice(address);
if (device == null) {
device = new LocalBluetoothDevice(mLocalManager.getContext(), address);
mDevices.add(device);
- dispatchDeviceAdded(device);
+ dispatchDeviceAdded(device);
+ deviceAdded = true;
}
}
+
+ return deviceAdded;
}
public synchronized List getDevicesCopy() {
@@ -157,23 +161,33 @@ public class LocalBluetoothDeviceManager {
public synchronized void onBondingStateChanged(String address, int bondState) {
LocalBluetoothDevice device = findDevice(address);
if (device == null) {
- Log.e(TAG, "Got bonding state changed for " + address +
- ", but we have no record of that device.");
+ if (!readPairedDevices()) {
+ Log.e(TAG, "Got bonding state changed for " + address +
+ ", but we have no record of that device.");
+ }
return;
}
- device.setBondState(bondState); //TODO: might be unecessary
- checkForDeviceRemoval(device);
+ device.refresh();
if (bondState == BluetoothDevice.BOND_BONDED) {
// Auto-connect after pairing
device.connect();
}
}
-
- public synchronized void onBondingError(String address) {
+
+ /**
+ * Called when there is a bonding error.
+ *
+ * @param address The address of the remote device.
+ * @param reason The reason, one of the error reasons from
+ * BluetoothDevice.UNBOND_REASON_*
+ */
+ public synchronized void onBondingError(String address, int reason) {
mLocalManager.showError(address, R.string.bluetooth_error_title,
- R.string.bluetooth_pairing_error_message);
+ (reason == BluetoothDevice.UNBOND_REASON_AUTH_FAILED) ?
+ R.string.bluetooth_pairing_pin_error_message :
+ R.string.bluetooth_pairing_error_message);
}
public synchronized void onProfileStateChanged(String address) {
@@ -205,4 +219,11 @@ public class LocalBluetoothDeviceManager {
checkForDeviceRemoval(device);
}
}
+
+ public synchronized void onBtClassChanged(String address) {
+ LocalBluetoothDevice device = findDevice(address);
+ if (device != null) {
+ device.refreshBtClass();
+ }
+ }
}
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
index f8275b50d60..4671fac6e8e 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
@@ -23,6 +23,7 @@ import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
+import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
@@ -51,11 +52,13 @@ public class LocalBluetoothManager {
private Context mContext;
/** If a BT-related activity is in the foreground, this will be it. */
private Activity mForegroundActivity;
-
+ private AlertDialog mErrorDialog = null;
+
private BluetoothDevice mManager;
private LocalBluetoothDeviceManager mLocalDeviceManager;
private BluetoothEventRedirector mEventRedirector;
+ private BluetoothA2dp mBluetoothA2dp;
public static enum ExtendedBluetoothState { ENABLED, ENABLING, DISABLED, DISABLING, UNKNOWN }
private ExtendedBluetoothState mState = ExtendedBluetoothState.UNKNOWN;
@@ -95,7 +98,9 @@ public class LocalBluetoothManager {
mEventRedirector = new BluetoothEventRedirector(this);
mEventRedirector.start();
-
+
+ mBluetoothA2dp = new BluetoothA2dp(context);
+
return true;
}
@@ -112,6 +117,10 @@ public class LocalBluetoothManager {
}
public void setForegroundActivity(Activity activity) {
+ if (mErrorDialog != null) {
+ mErrorDialog.dismiss();
+ mErrorDialog = null;
+ }
mForegroundActivity = activity;
}
@@ -149,9 +158,23 @@ public class LocalBluetoothManager {
*/
dispatchScanningStateChanged(true);
} else {
-
- // Don't scan more than frequently than SCAN_EXPIRATION_MS, unless forced
- if (!force && mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) return;
+ if (!force) {
+ // Don't scan more than frequently than SCAN_EXPIRATION_MS,
+ // unless forced
+ if (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) {
+ return;
+ }
+
+ // If we are playing music, don't scan unless forced.
+ List sinks = mBluetoothA2dp.listConnectedSinks();
+ if (sinks != null) {
+ for (String address : sinks) {
+ if (mBluetoothA2dp.getSinkState(address) == BluetoothA2dp.STATE_PLAYING) {
+ return;
+ }
+ }
+ }
+ }
if (mManager.startDiscovery(true)) {
mLastScan = System.currentTimeMillis();
@@ -226,10 +249,6 @@ public class LocalBluetoothManager {
}
}
- public boolean createBonding(String address) {
- return mManager.createBond(address);
- }
-
public void showError(String address, int titleResId, int messageResId) {
LocalBluetoothDevice device = mLocalDeviceManager.findDevice(address);
if (device == null) return;
@@ -239,7 +258,7 @@ public class LocalBluetoothManager {
if (mForegroundActivity != null) {
// Need an activity context to show a dialog
- AlertDialog ad = new AlertDialog.Builder(mForegroundActivity)
+ mErrorDialog = new AlertDialog.Builder(mForegroundActivity)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(titleResId)
.setMessage(message)
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
index a1a2af60c09..50edf86f4f9 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
@@ -132,6 +132,12 @@ public abstract class LocalBluetoothProfileManager {
@Override
public int connect(String address) {
+ List sinks = mService.listConnectedSinks();
+ if (sinks != null) {
+ for (String sinkAddress : sinks) {
+ mService.disconnectSink(sinkAddress);
+ }
+ }
return mService.connectSink(address);
}
diff --git a/src/com/android/settings/deviceinfo/Memory.java b/src/com/android/settings/deviceinfo/Memory.java
index 86e642345b8..75a84b71909 100644
--- a/src/com/android/settings/deviceinfo/Memory.java
+++ b/src/com/android/settings/deviceinfo/Memory.java
@@ -48,11 +48,13 @@ public class Memory extends PreferenceActivity {
private static final String MEMORY_SD_UNMOUNT = "memory_sd_unmount";
+ private static final String MEMORY_SD_FORMAT = "memory_sd_format";
private Resources mRes;
private Preference mSdSize;
private Preference mSdAvail;
private Preference mSdUnmount;
+ private Preference mSdFormat;
// Access using getMountService()
private IMountService mMountService = null;
@@ -67,6 +69,7 @@ public class Memory extends PreferenceActivity {
mSdSize = findPreference(MEMORY_SD_SIZE);
mSdAvail = findPreference(MEMORY_SD_AVAIL);
mSdUnmount = findPreference(MEMORY_SD_UNMOUNT);
+ mSdFormat = findPreference(MEMORY_SD_FORMAT);
}
@Override
@@ -78,6 +81,8 @@ public class Memory extends PreferenceActivity {
intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SHARED);
intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
+ intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTABLE);
+ intentFilter.addAction(Intent.ACTION_MEDIA_NOFS);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
intentFilter.addDataScheme("file");
@@ -109,6 +114,11 @@ public class Memory extends PreferenceActivity {
if (preference == mSdUnmount) {
unmount();
return true;
+ } else if (preference == mSdFormat) {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setClass(this, com.android.settings.MediaFormat.class);
+ startActivity(intent);
+ return true;
}
return false;
@@ -134,7 +144,7 @@ public class Memory extends PreferenceActivity {
updateMemoryStatus();
}
}
-
+
private void updateMemoryStatus() {
String status = Environment.getExternalStorageState();
String readOnly = "";
@@ -143,6 +153,8 @@ public class Memory extends PreferenceActivity {
readOnly = mRes.getString(R.string.read_only);
}
+ mSdFormat.setEnabled(false);
+
if (status.equals(Environment.MEDIA_MOUNTED)) {
try {
File path = Environment.getExternalStorageDirectory();
@@ -164,6 +176,14 @@ public class Memory extends PreferenceActivity {
mSdSize.setSummary(mRes.getString(R.string.sd_unavailable));
mSdAvail.setSummary(mRes.getString(R.string.sd_unavailable));
mSdUnmount.setEnabled(false);
+
+ if (status.equals(Environment.MEDIA_UNMOUNTED) ||
+ status.equals(Environment.MEDIA_NOFS) ||
+ status.equals(Environment.MEDIA_UNMOUNTABLE) ) {
+ mSdFormat.setEnabled(true);
+ }
+
+
}
File path = Environment.getDataDirectory();
diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java
index b7aceb1d31f..96366b8914e 100644
--- a/src/com/android/settings/deviceinfo/Status.java
+++ b/src/com/android/settings/deviceinfo/Status.java
@@ -51,7 +51,6 @@ import java.lang.ref.WeakReference;
* # Network
* # Roaming
* # IMEI
- * # IMSI
* # Network type
* # Signal Strength
* # Battery Strength : TODO
@@ -66,8 +65,8 @@ public class Status extends PreferenceActivity {
private static final String KEY_BT_ADDRESS = "bt_address";
private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 200;
private static final int EVENT_SERVICE_STATE_CHANGED = 300;
-
- private static final int EVENT_FIX_UPTIME = 500;
+
+ private static final int EVENT_UPDATE_STATS = 500;
private TelephonyManager mTelephonyManager;
private Phone mPhone = null;
@@ -108,9 +107,9 @@ public class Status extends PreferenceActivity {
status.updateServiceState(serviceState);
break;
- case EVENT_FIX_UPTIME:
+ case EVENT_UPDATE_STATS:
status.updateTimes();
- sendMessageDelayed(obtainMessage(EVENT_FIX_UPTIME), 1000);
+ sendEmptyMessageDelayed(EVENT_UPDATE_STATS, 1000);
break;
}
}
@@ -187,7 +186,6 @@ public class Status extends PreferenceActivity {
setSummaryText("imei_sv",
((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
.getDeviceSoftwareVersion());
- setSummaryText("imsi", mPhone.getSubscriberId());
setSummaryText("number", mPhone.getLine1Number());
mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);
@@ -196,7 +194,7 @@ public class Status extends PreferenceActivity {
setWifiStatus();
setBtStatus();
- }
+ }
@Override
protected void onResume() {
@@ -212,7 +210,7 @@ public class Status extends PreferenceActivity {
mTelephonyManager.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_FIX_UPTIME), 0);
+ mHandler.sendEmptyMessage(EVENT_UPDATE_STATS);
}
@Override
@@ -222,7 +220,7 @@ public class Status extends PreferenceActivity {
mPhoneStateReceiver.unregisterIntent();
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
unregisterReceiver(mBatteryInfoReceiver);
- mHandler.removeMessages(EVENT_FIX_UPTIME);
+ mHandler.removeMessages(EVENT_UPDATE_STATS);
}
/**
diff --git a/src/com/android/settings/quicklaunch/QuickLaunchSettings.java b/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
index 2ec685db0e0..4d44524ac03 100644
--- a/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
+++ b/src/com/android/settings/quicklaunch/QuickLaunchSettings.java
@@ -16,8 +16,6 @@
package com.android.settings.quicklaunch;
-import com.android.settings.R;
-
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
@@ -28,10 +26,9 @@ import android.os.Bundle;
import android.os.Handler;
import android.preference.Preference;
import android.preference.PreferenceActivity;
-import android.preference.PreferenceCategory;
+import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Settings.Bookmarks;
-import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -40,6 +37,8 @@ import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
+import com.android.settings.R;
+
/**
* Settings activity for quick launch.
*
@@ -76,7 +75,7 @@ public class QuickLaunchSettings extends PreferenceActivity implements
private SparseBooleanArray mBookmarkedShortcuts;
/** Preference category to hold the shortcut preferences. */
- private PreferenceCategory mShortcutCategory;
+ private PreferenceGroup mShortcutGroup;
/** Mapping of a shortcut to its preference. */
private SparseArray mShortcutToPreference;
@@ -93,7 +92,7 @@ public class QuickLaunchSettings extends PreferenceActivity implements
addPreferencesFromResource(R.xml.quick_launch_settings);
- mShortcutCategory = (PreferenceCategory) findPreference(KEY_SHORTCUT_CATEGORY);
+ mShortcutGroup = (PreferenceGroup) findPreference(KEY_SHORTCUT_CATEGORY);
mShortcutToPreference = new SparseArray();
mBookmarksObserver = new BookmarksObserver(mUiHandler);
initShortcutPreferences();
@@ -252,7 +251,7 @@ public class QuickLaunchSettings extends PreferenceActivity implements
private ShortcutPreference createPreference(char shortcut) {
ShortcutPreference pref = new ShortcutPreference(QuickLaunchSettings.this, shortcut);
- mShortcutCategory.addPreference(pref);
+ mShortcutGroup.addPreference(pref);
mShortcutToPreference.put(shortcut, pref);
return pref;
}
diff --git a/src/com/android/settings/wifi/AccessPointDialog.java b/src/com/android/settings/wifi/AccessPointDialog.java
index 917ed967f3f..919f7fc92f7 100644
--- a/src/com/android/settings/wifi/AccessPointDialog.java
+++ b/src/com/android/settings/wifi/AccessPointDialog.java
@@ -24,6 +24,7 @@ import android.content.DialogInterface;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
+import android.text.InputType;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.text.method.PasswordTransformationMethod;
@@ -589,11 +590,9 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On
private void setShowPassword(boolean showPassword) {
if (mPasswordEdit != null) {
- // Toggle password
- mPasswordEdit.setTransformationMethod(
- showPassword ?
- null :
- PasswordTransformationMethod.getInstance());
+ mPasswordEdit.setInputType(InputType.TYPE_CLASS_TEXT |
+ (showPassword ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
+ : InputType.TYPE_TEXT_VARIATION_PASSWORD));
}
}
diff --git a/src/com/android/settings/wifi/AccessPointState.java b/src/com/android/settings/wifi/AccessPointState.java
index c22495434f4..25698023833 100644
--- a/src/com/android/settings/wifi/AccessPointState.java
+++ b/src/com/android/settings/wifi/AccessPointState.java
@@ -47,24 +47,7 @@ public final class AccessPointState implements Comparable, Par
private static final String ADHOC_CAPABILITY = "[IBSS]";
/** String present in capabilities if the scan result is enterprise secured */
private static final String ENTERPRISE_CAPABILITY = "-EAP-";
-
- // Localized strings for different security types
- private static String LOCALIZED_WPA2;
- private static String LOCALIZED_WPA;
- private static String LOCALIZED_WEP;
- private static String LOCALIZED_OPEN;
- private static String LOCALIZED_UNKNOWN;
- private static String LOCALIZED_VERBOSE_WPA2;
- private static String LOCALIZED_VERBOSE_WPA;
- private static String LOCALIZED_VERBOSE_WEP;
- private static String LOCALIZED_VERBOSE_OPEN;
-
- // Localized strings for various messages
- private static String SUMMARY_NOT_IN_RANGE;
- private static String SUMMARY_REMEMBERED;
- private static String SUMMARY_CONNECTION_FAILED;
-
public static final String BSSID_ANY = "any";
public static final int NETWORK_ID_NOT_SET = -1;
/** This should be used with care! */
@@ -147,31 +130,8 @@ public final class AccessPointState implements Comparable, Par
void setContext(Context context) {
mContext = context;
- setStrings();
}
- private void setStrings() {
- final Context c = mContext;
-
- if (SUMMARY_NOT_IN_RANGE == null && c != null) {
- SUMMARY_NOT_IN_RANGE = c.getString(R.string.summary_not_in_range);
- SUMMARY_REMEMBERED = c.getString(R.string.summary_remembered);
- SUMMARY_CONNECTION_FAILED = c.getString(R.string.summary_connection_failed);
-
- LOCALIZED_OPEN = c.getString(R.string.wifi_security_open);
- LOCALIZED_WEP = c.getString(R.string.wifi_security_wep);
- LOCALIZED_WPA = c.getString(R.string.wifi_security_wpa);
- LOCALIZED_WPA2 = c.getString(R.string.wifi_security_wpa2);
-
- LOCALIZED_VERBOSE_OPEN = c.getString(R.string.wifi_security_verbose_open);
- LOCALIZED_VERBOSE_WEP = c.getString(R.string.wifi_security_verbose_wep);
- LOCALIZED_VERBOSE_WPA = c.getString(R.string.wifi_security_verbose_wpa);
- LOCALIZED_VERBOSE_WPA2 = c.getString(R.string.wifi_security_verbose_wpa2);
-
- LOCALIZED_UNKNOWN = c.getString(R.string.wifi_security_unknown);
- }
- }
-
public void setNetworkId(int networkId) {
this.networkId = networkId;
}
@@ -311,12 +271,12 @@ public final class AccessPointState implements Comparable, Par
}
public String getHumanReadableSecurity() {
- if (security.equals(OPEN)) return LOCALIZED_OPEN;
- else if (security.equals(WEP)) return LOCALIZED_WEP;
- else if (security.equals(WPA)) return LOCALIZED_WPA;
- else if (security.equals(WPA2)) return LOCALIZED_WPA2;
+ if (security.equals(OPEN)) return mContext.getString(R.string.wifi_security_open);
+ else if (security.equals(WEP)) return mContext.getString(R.string.wifi_security_wep);
+ else if (security.equals(WPA)) return mContext.getString(R.string.wifi_security_wpa);
+ else if (security.equals(WPA2)) return mContext.getString(R.string.wifi_security_wpa2);
- return LOCALIZED_UNKNOWN;
+ return mContext.getString(R.string.wifi_security_unknown);
}
public void updateFromScanResult(ScanResult scanResult) {
@@ -719,22 +679,22 @@ public final class AccessPointState implements Comparable, Par
buildSummary(sb, WifiStatus.getPrintable(mContext, status), true);
} else if (!seen) {
- buildSummary(sb, SUMMARY_NOT_IN_RANGE, true);
+ buildSummary(sb, mContext.getString(R.string.summary_not_in_range), true);
// Remembered comes second in this case
if (!primary && configured) {
- buildSummary(sb, SUMMARY_REMEMBERED, true);
+ buildSummary(sb, mContext.getString(R.string.summary_remembered), true);
}
} else {
if (configured && disabled) {
// The connection failure overrides all in this case
- return SUMMARY_CONNECTION_FAILED;
+ return mContext.getString(R.string.summary_connection_failed);
}
// Remembered comes first in this case
if (!primary && configured) {
- buildSummary(sb, SUMMARY_REMEMBERED, true);
+ buildSummary(sb, mContext.getString(R.string.summary_remembered), true);
}
// If it is seen (and not the primary), show the security type
@@ -749,13 +709,13 @@ public final class AccessPointState implements Comparable, Par
private String getVerboseSecurity() {
if (WEP.equals(security)) {
- return LOCALIZED_VERBOSE_WEP;
+ return mContext.getString(R.string.wifi_security_verbose_wep);
} else if (WPA.equals(security)) {
- return LOCALIZED_VERBOSE_WPA;
+ return mContext.getString(R.string.wifi_security_verbose_wpa);
} else if (WPA2.equals(security)) {
- return LOCALIZED_VERBOSE_WPA2;
+ return mContext.getString(R.string.wifi_security_verbose_wpa2);
} else if (OPEN.equals(security)) {
- return LOCALIZED_VERBOSE_OPEN;
+ return mContext.getString(R.string.wifi_security_verbose_open);
} else {
return null;
}
diff --git a/src/com/android/settings/wifi/AdvancedSettings.java b/src/com/android/settings/wifi/AdvancedSettings.java
index 54aab4be4b5..323d5c77095 100644
--- a/src/com/android/settings/wifi/AdvancedSettings.java
+++ b/src/com/android/settings/wifi/AdvancedSettings.java
@@ -95,6 +95,7 @@ public class AdvancedSettings extends PreferenceActivity
if (validChannelCounts == null) {
Toast.makeText(this, R.string.wifi_setting_num_channels_error,
Toast.LENGTH_SHORT).show();
+ pref.setEnabled(false);
return;
}
String[] entries = new String[validChannelCounts.length];
@@ -107,6 +108,7 @@ public class AdvancedSettings extends PreferenceActivity
}
pref.setEntries(entries);
pref.setEntryValues(entryValues);
+ pref.setEnabled(true);
int numChannels = wifiManager.getNumAllowedChannels();
if (numChannels >= 0) {
pref.setValue(String.valueOf(numChannels));
diff --git a/src/com/android/settings/wifi/WifiStatus.java b/src/com/android/settings/wifi/WifiStatus.java
index d4b6431d069..e10ab8ded94 100644
--- a/src/com/android/settings/wifi/WifiStatus.java
+++ b/src/com/android/settings/wifi/WifiStatus.java
@@ -20,51 +20,9 @@ import com.android.settings.R;
import android.content.Context;
import android.net.NetworkInfo;
-import android.net.wifi.WifiInfo;
import android.text.TextUtils;
public class WifiStatus {
-
- // e.g., "Connecting"
- public static String sScanning;
- public static String sConnecting;
- public static String sAuthenticating;
- public static String sObtainingIp;
- public static String sConnected;
- public static String sDisconnecting;
- public static String sDisconnected;
- public static String sFailed;
-
- // e.g., "Connecting to %1$s"
- public static String sScanningFragment;
- public static String sConnectingFragment;
- public static String sAuthenticatingFragment;
- public static String sObtainingIpFragment;
- public static String sConnectedFragment;
- public static String sDisconnectingFragment;
- public static String sDisconnectedFragment;
- public static String sFailedFragment;
-
- private static void fillStrings(Context context) {
- sScanning = context.getString(R.string.status_scanning);
- sConnecting = context.getString(R.string.status_connecting);
- sAuthenticating = context.getString(R.string.status_authenticating);
- sObtainingIp = context.getString(R.string.status_obtaining_ip);
- sConnected = context.getString(R.string.status_connected);
- sDisconnecting = context.getString(R.string.status_disconnecting);
- sDisconnected = context.getString(R.string.status_disconnected);
- sFailed = context.getString(R.string.status_failed);
-
- sScanningFragment = context.getString(R.string.fragment_status_scanning);
- sConnectingFragment = context.getString(R.string.fragment_status_connecting);
- sAuthenticatingFragment = context.getString(R.string.fragment_status_authenticating);
- sObtainingIpFragment = context.getString(R.string.fragment_status_obtaining_ip);
- sConnectedFragment = context.getString(R.string.fragment_status_connected);
- sDisconnectingFragment = context.getString(R.string.fragment_status_disconnecting);
- sDisconnectedFragment = context.getString(R.string.fragment_status_disconnected);
- sFailedFragment = context.getString(R.string.fragment_status_failed);
- }
-
public static String getStatus(Context context, String ssid,
NetworkInfo.DetailedState detailedState) {
@@ -85,27 +43,23 @@ public class WifiStatus {
public static String getPrintable(Context context,
NetworkInfo.DetailedState detailedState) {
- if (sScanning == null) {
- fillStrings(context);
- }
-
switch (detailedState) {
case AUTHENTICATING:
- return sAuthenticating;
+ return context.getString(R.string.status_authenticating);
case CONNECTED:
- return sConnected;
+ return context.getString(R.string.status_connected);
case CONNECTING:
- return sConnecting;
+ return context.getString(R.string.status_connecting);
case DISCONNECTED:
- return sDisconnected;
+ return context.getString(R.string.status_disconnected);
case DISCONNECTING:
- return sDisconnecting;
+ return context.getString(R.string.status_disconnecting);
case FAILED:
- return sFailed;
+ return context.getString(R.string.status_failed);
case OBTAINING_IPADDR:
- return sObtainingIp;
+ return context.getString(R.string.status_obtaining_ip);
case SCANNING:
- return sScanning;
+ return context.getString(R.string.status_scanning);
default:
return null;
}
@@ -114,35 +68,31 @@ public class WifiStatus {
public static String getPrintableFragment(Context context,
NetworkInfo.DetailedState detailedState, String apName) {
- if (sScanningFragment == null) {
- fillStrings(context);
- }
-
String fragment = null;
switch (detailedState) {
case AUTHENTICATING:
- fragment = sAuthenticatingFragment;
+ fragment = context.getString(R.string.fragment_status_authenticating);
break;
case CONNECTED:
- fragment = sConnectedFragment;
+ fragment = context.getString(R.string.fragment_status_connected);
break;
case CONNECTING:
- fragment = sConnectingFragment;
+ fragment = context.getString(R.string.fragment_status_connecting);
break;
case DISCONNECTED:
- fragment = sDisconnectedFragment;
+ fragment = context.getString(R.string.fragment_status_disconnected);
break;
case DISCONNECTING:
- fragment = sDisconnectingFragment;
+ fragment = context.getString(R.string.fragment_status_disconnecting);
break;
case FAILED:
- fragment = sFailedFragment;
+ fragment = context.getString(R.string.fragment_status_failed);
break;
case OBTAINING_IPADDR:
- fragment = sObtainingIpFragment;
+ fragment = context.getString(R.string.fragment_status_obtaining_ip);
break;
case SCANNING:
- fragment = sScanningFragment;
+ fragment = context.getString(R.string.fragment_status_scanning);
break;
}