From 2c9b326fdbfe64dc778b5eabf80017249a509351 Mon Sep 17 00:00:00 2001 From: Jason Parekh <> Date: Tue, 24 Mar 2009 17:48:28 -0700 Subject: [PATCH 001/126] Automated import from //branches/donutburger/...@140507,140507 --- res/values/strings.xml | 4 +++- src/com/android/settings/SoundAndDisplaySettings.java | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 55a153b3ece..67c095d6d3d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -751,8 +751,10 @@ Set ringtones, notifications, screen brightness Silent mode - + All sounds except media & alarms are silenced + + All sounds except media are silenced Phone ringtone diff --git a/src/com/android/settings/SoundAndDisplaySettings.java b/src/com/android/settings/SoundAndDisplaySettings.java index 8905b859fd7..e8cb10f98d9 100644 --- a/src/com/android/settings/SoundAndDisplaySettings.java +++ b/src/com/android/settings/SoundAndDisplaySettings.java @@ -162,6 +162,13 @@ public class SoundAndDisplaySettings extends PreferenceActivity implements mVibrate.setChecked(vibrateSetting); } + int silentModeStreams = Settings.System.getInt(getContentResolver(), + Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); + boolean isAlarmInclSilentMode = (silentModeStreams & (1 << AudioManager.STREAM_ALARM)) != 0; + mSilent.setSummary(isAlarmInclSilentMode ? + R.string.silent_mode_incl_alarm_summary : + R.string.silent_mode_summary); + boolean animations = true; try { mAnimationScales = mWindowManager.getAnimationScales(); From de56037290f94c0fdc4f42c6f9e85fdf2a1feb55 Mon Sep 17 00:00:00 2001 From: Joe Onorato <> Date: Tue, 24 Mar 2009 17:49:03 -0700 Subject: [PATCH 002/126] Automated import from //branches/donutburger/...@140511,140511 --- AndroidManifest.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ef5e072f952..a70249294c9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -373,7 +373,9 @@ - + @@ -474,7 +476,9 @@ - + From 1bae5b41b7cc0f028f9e1615fa0cf80d503ffdb6 Mon Sep 17 00:00:00 2001 From: John Huang <> Date: Tue, 24 Mar 2009 18:26:28 -0700 Subject: [PATCH 003/126] Automated import from //branches/donutburger/...@140756,140756 --- res/layout/apn_preference_layout.xml | 65 +++++++++ src/com/android/settings/ApnPreference.java | 151 ++++++++++++++++++++ src/com/android/settings/ApnSettings.java | 150 ++++++++++++++++--- 3 files changed, 349 insertions(+), 17 deletions(-) create mode 100644 res/layout/apn_preference_layout.xml create mode 100644 src/com/android/settings/ApnPreference.java diff --git a/res/layout/apn_preference_layout.xml b/res/layout/apn_preference_layout.xml new file mode 100644 index 00000000000..2a7c2e9454d --- /dev/null +++ b/res/layout/apn_preference_layout.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + diff --git a/src/com/android/settings/ApnPreference.java b/src/com/android/settings/ApnPreference.java new file mode 100644 index 00000000000..74fb90216e2 --- /dev/null +++ b/src/com/android/settings/ApnPreference.java @@ -0,0 +1,151 @@ +/* + * 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.ContentUris; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.preference.Preference; +import android.provider.Telephony; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.view.View.OnClickListener; +import android.widget.CompoundButton; +import android.widget.RadioButton; +import android.widget.RelativeLayout; + +public class ApnPreference extends Preference implements + CompoundButton.OnCheckedChangeListener, OnClickListener { + final static String TAG = "ApnPreference"; + + /** + * @param context + * @param attrs + * @param defStyle + */ + public ApnPreference(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(); + } + + /** + * @param context + * @param attrs + */ + public ApnPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + /** + * @param context + */ + public ApnPreference(Context context) { + super(context); + init(); + } + + private static String mSelectedKey = null; + private static CompoundButton mCurrentChecked = null; + private boolean mProtectFromCheckedChange = false; + private boolean mSelectable = true; + + @Override + public View getView(View convertView, ViewGroup parent) { + View view = super.getView(convertView, parent); + + View widget = view.findViewById(R.id.apn_radiobutton); + if ((widget != null) && widget instanceof RadioButton) { + RadioButton rb = (RadioButton) widget; + if (mSelectable) { + rb.setOnCheckedChangeListener(this); + + boolean isChecked = getKey().equals(mSelectedKey); + if (isChecked) { + mCurrentChecked = rb; + mSelectedKey = getKey(); + } + + mProtectFromCheckedChange = true; + rb.setChecked(isChecked); + mProtectFromCheckedChange = false; + } else { + rb.setVisibility(View.GONE); + } + } + + View textLayout = view.findViewById(R.id.text_layout); + if ((textLayout != null) && textLayout instanceof RelativeLayout) { + textLayout.setOnClickListener(this); + } + + return view; + } + + private void init() { + setLayoutResource(R.layout.apn_preference_layout); + } + + public boolean isChecked() { + return getKey().equals(mSelectedKey); + } + + public void setChecked(boolean checked) { + mSelectedKey = getKey(); + } + + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + Log.i(TAG, "ID: " + getKey() + " :" + isChecked); + if (mProtectFromCheckedChange) { + return; + } + + if (isChecked) { + if (mCurrentChecked != null) { + mCurrentChecked.setChecked(false); + } + mCurrentChecked = buttonView; + mSelectedKey = getKey(); + callChangeListener(mSelectedKey); + } else { + mCurrentChecked = null; + mSelectedKey = null; + } + } + + public void onClick(android.view.View v) { + if ((v != null) && (R.id.text_layout == v.getId())) { + Context context = getContext(); + if (context != null) { + int pos = Integer.parseInt(getKey()); + Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos); + context.startActivity(new Intent(Intent.ACTION_EDIT, url)); + } + } + } + + public void setSelectable(boolean selectable) { + mSelectable = selectable; + } + + public boolean getSelectable() { + return mSelectable; + } +} diff --git a/src/com/android/settings/ApnSettings.java b/src/com/android/settings/ApnSettings.java index 87e3412d2a4..ecfdb2479fa 100644 --- a/src/com/android/settings/ApnSettings.java +++ b/src/com/android/settings/ApnSettings.java @@ -18,10 +18,13 @@ package com.android.settings; import android.app.Dialog; import android.app.ProgressDialog; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.ContentUris; +import android.content.ContentValues; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -34,20 +37,33 @@ import android.preference.PreferenceActivity; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; import android.provider.Telephony; -import android.text.TextUtils; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; -public class ApnSettings extends PreferenceActivity { +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.telephony.TelephonyProperties; + +import java.util.ArrayList; + +public class ApnSettings extends PreferenceActivity implements + Preference.OnPreferenceChangeListener { + static final String TAG = "ApnSettings"; public static final String EXTRA_POSITION = "position"; public static final String RESTORE_CARRIERS_URI = "content://telephony/carriers/restore"; + public static final String PREFERRED_APN_URI = + "content://telephony/carriers/preferapn"; + + public static final String APN_ID = "apn_id"; private static final int ID_INDEX = 0; private static final int NAME_INDEX = 1; private static final int APN_INDEX = 2; + private static final int TYPES_INDEX = 3; private static final int MENU_NEW = Menu.FIRST; private static final int MENU_RESTORE = Menu.FIRST + 1; @@ -58,25 +74,62 @@ public class ApnSettings extends PreferenceActivity { private static final int DIALOG_RESTORE_DEFAULTAPN = 1001; private static final Uri DEFAULTAPN_URI = Uri.parse(RESTORE_CARRIERS_URI); + private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI); private static boolean mRestoreDefaultApnMode; private RestoreApnUiHandler mRestoreApnUiHandler; private RestoreApnProcessHandler mRestoreApnProcessHandler; - private Cursor mCursor; + private String mSelectedKey; + + private IntentFilter mMobileStateFilter; + + private final BroadcastReceiver mMobileStateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals( + TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { + Phone.DataState state = getMobileDataState(intent); + switch (state) { + case CONNECTED: + if (!mRestoreDefaultApnMode) { + fillList(); + } else { + showDialog(DIALOG_RESTORE_DEFAULTAPN); + } + break; + } + } + } + }; + + private static Phone.DataState getMobileDataState(Intent intent) { + String str = intent.getStringExtra(Phone.STATE_KEY); + if (str != null) { + return Enum.valueOf(Phone.DataState.class, str); + } else { + return Phone.DataState.DISCONNECTED; + } + } @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.apn_settings); + getListView().setItemsCanFocus(true); + + mMobileStateFilter = new IntentFilter( + TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); } @Override protected void onResume() { super.onResume(); + registerReceiver(mMobileStateReceiver, mMobileStateFilter); + if (!mRestoreDefaultApnMode) { fillList(); } else { @@ -84,29 +137,59 @@ public class ApnSettings extends PreferenceActivity { } } + @Override + protected void onPause() { + super.onPause(); + + unregisterReceiver(mMobileStateReceiver); + } + private void fillList() { - mCursor = managedQuery(Telephony.Carriers.CONTENT_URI, new String[] { - "_id", "name", "apn"}, null, Telephony.Carriers.DEFAULT_SORT_ORDER); + String where = "numeric=\"" + + android.os.SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC, "") + + "\""; + + Cursor cursor = managedQuery(Telephony.Carriers.CONTENT_URI, new String[] { + "_id", "name", "apn", "type"}, where, + Telephony.Carriers.DEFAULT_SORT_ORDER); PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list"); apnList.removeAll(); - mCursor.moveToFirst(); - while (!mCursor.isAfterLast()) { - String name = mCursor.getString(NAME_INDEX); - String apn = mCursor.getString(APN_INDEX); + ArrayList mmsApnList = new ArrayList(); - if (name != null && apn != null && TextUtils.getTrimmedLength(name) > 0 - && TextUtils.getTrimmedLength(apn) > 0) { - Preference pref = new Preference((Context) this); - pref.setKey(mCursor.getString(ID_INDEX)); - pref.setTitle(name); - pref.setSummary(apn); - pref.setPersistent(false); + mSelectedKey = getSelectedApnKey(); + cursor.moveToFirst(); + while (!cursor.isAfterLast()) { + String name = cursor.getString(NAME_INDEX); + String apn = cursor.getString(APN_INDEX); + String key = cursor.getString(ID_INDEX); + String type = cursor.getString(TYPES_INDEX); + + ApnPreference pref = new ApnPreference(this); + + pref.setKey(key); + pref.setTitle(name); + pref.setSummary(apn); + pref.setPersistent(false); + pref.setOnPreferenceChangeListener(this); + + boolean selectable = ((type == null) || !type.equals("mms")); + pref.setSelectable(selectable); + if (selectable) { + if ((mSelectedKey != null) && mSelectedKey.equals(key)) { + pref.setChecked(true); + } apnList.addPreference(pref); + } else { + mmsApnList.add(pref); } + cursor.moveToNext(); + } + cursor.close(); - mCursor.moveToNext(); + for (Preference preference : mmsApnList) { + apnList.addPreference(preference); } } @@ -148,6 +231,39 @@ public class ApnSettings extends PreferenceActivity { return true; } + public boolean onPreferenceChange(Preference preference, Object newValue) { + Log.d(TAG, "onPreferenceChange(): Preference - " + preference + + ", newValue - " + newValue + ", newValue type - " + + newValue.getClass()); + if (newValue instanceof String) { + setSelectedApnKey((String) newValue); + } + + return true; + } + + private void setSelectedApnKey(String key) { + mSelectedKey = key; + ContentResolver resolver = getContentResolver(); + + ContentValues values = new ContentValues(); + values.put(APN_ID, mSelectedKey); + resolver.update(PREFERAPN_URI, values, null, null); + } + + private String getSelectedApnKey() { + String key = null; + + Cursor cursor = managedQuery(PREFERAPN_URI, new String[] {"_id"}, + null, Telephony.Carriers.DEFAULT_SORT_ORDER); + if (cursor.getCount() > 0) { + cursor.moveToFirst(); + key = cursor.getString(ID_INDEX); + } + cursor.close(); + return key; + } + private boolean restoreDefaultApn() { showDialog(DIALOG_RESTORE_DEFAULTAPN); mRestoreDefaultApnMode = true; From ed9969a652f0c07daffd8fd23735128a152fdb1c Mon Sep 17 00:00:00 2001 From: Joe Onorato <> Date: Tue, 24 Mar 2009 18:40:50 -0700 Subject: [PATCH 004/126] Automated import from //branches/donutburger/...@140841,140841 --- AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a70249294c9..12c8e9aaea8 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -375,7 +375,7 @@ + android:theme="@android:style/Theme.Light"> From b5f7b16051c16a2924b819ec87b213933500f0c5 Mon Sep 17 00:00:00 2001 From: Eric Fischer <> Date: Tue, 24 Mar 2009 18:47:01 -0700 Subject: [PATCH 005/126] Automated import from //branches/donutburger/...@140873,140873 --- res/values-ja/strings.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 7e358b218d1..a05f7dffec5 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -412,7 +412,7 @@ "該当なし" "端末の状態" "端末の状態" - "電話番号、端末識別番号、電波状態など" + "電池残量、電話番号、ネットワークなど" "SDカード & 端末容量" "SDカードの取り外し、空き容量の表示" "電話番号" @@ -552,7 +552,7 @@ "いつもこのアプリケーションを選択する操作" "許可" "キャッシュ" - "キャッシュをクリア" + "キャッシュを消去" "キャッシュ" "コントロール" "強制停止" @@ -601,6 +601,8 @@ "英語: Spaceキー2回でピリオド(.)を挿入" "パスワードを表示" "入力時にパスワードを表示する" + + "ユーザー辞書" "ユーザー辞書" "ユーザー辞書への語句の追加と削除" From b22cc181183fe17702392f6807b9b82648d557b5 Mon Sep 17 00:00:00 2001 From: Suchi Amalapurapu <> Date: Tue, 24 Mar 2009 18:47:42 -0700 Subject: [PATCH 006/126] Automated import from //branches/donutburger/...@140876,140876 --- .../android/settings/ManageApplications.java | 288 ++++++++++++------ 1 file changed, 192 insertions(+), 96 deletions(-) diff --git a/src/com/android/settings/ManageApplications.java b/src/com/android/settings/ManageApplications.java index 7f2e2cea263..dbbd249e8f9 100644 --- a/src/com/android/settings/ManageApplications.java +++ b/src/com/android/settings/ManageApplications.java @@ -39,6 +39,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.SystemClock; import android.text.format.Formatter; import android.util.Config; import android.util.Log; @@ -60,11 +61,11 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.concurrent.CountDownLatch; /** * Activity to pick an application that will be used to display installation information and @@ -98,6 +99,8 @@ public class ManageApplications extends ListActivity implements // Log information boolean private boolean localLOGV = Config.LOGV || false; + private static final boolean DEBUG_SIZE = false; + private static final boolean DEBUG_TIME = false; // attributes used as keys when passing values to InstalledAppDetails activity public static final String APP_PKG_PREFIX = "com.android.settings."; @@ -142,6 +145,8 @@ public class ManageApplications extends ListActivity implements private static final int REFRESH_APP_RESOURCE = HANDLER_MESSAGE_BASE+7; private static final int REFRESH_DONE = HANDLER_MESSAGE_BASE+8; private static final int NEXT_LOAD_STEP = HANDLER_MESSAGE_BASE+9; + private static final int COMPUTE_END = HANDLER_MESSAGE_BASE+10; + // observer object used for computing pkg sizes private PkgSizeObserver mObserver; @@ -161,9 +166,6 @@ public class ManageApplications extends ListActivity implements private static final int DLG_BASE = 0; private static final int DLG_LOADING = DLG_BASE + 1; - // compute index used to track the application size computations - private int mComputeIndex; - // Size resource used for packages whose size computation failed for some reason private CharSequence mInvalidSizeStr; private CharSequence mComputingSizeStr; @@ -186,6 +188,7 @@ public class ManageApplications extends ListActivity implements // Thread to load resources ResourceLoaderThread mResourceThread; + private TaskRunner mSizeComputor; String mCurrentPkgName; @@ -204,6 +207,7 @@ public class ManageApplications extends ListActivity implements // initiate the first computation and loading of resources private boolean mJustCreated = true; private boolean mFirst = false; + private long mLoadTimeStart; /* * Handler class to handle messages for various operations @@ -250,9 +254,9 @@ public class ManageApplications extends ListActivity implements switch (msg.what) { case INIT_PKG_INFO: if(localLOGV) Log.i(TAG, "Message INIT_PKG_INFO"); - List newList = getInstalledApps(FILTER_APPS_ALL); if (!mJustCreated) { // Add or delete newly created packages by comparing lists + List newList = getInstalledApps(FILTER_APPS_ALL); updateAppList(newList); } // Retrieve the package list and init some structures @@ -269,26 +273,13 @@ public class ManageApplications extends ListActivity implements if(ps == null) { Log.i(TAG, "Invalid package stats for package:"+pkgName); } else { - int pkgId = mAppInfoAdapter.getIndex(pkgName); - if(mComputeIndex != pkgId) { - //spurious call from stale observer - Log.w(TAG, "Stale call back from PkgSizeObserver"); - break; - } mAppInfoAdapter.updateAppSize(pkgName, ps); } - mComputeIndex++; - if (mComputeIndex < mAppInfoAdapter.getCount()) { - // initiate compute package size for next pkg in list - mObserver.invokeGetSizeInfo(mAppInfoAdapter.getApplicationInfo( - mComputeIndex), - COMPUTE_PKG_SIZE_DONE); - } else { - // End computation here - mComputeSizes = true; - mFirst = true; - mHandler.sendEmptyMessage(NEXT_LOAD_STEP); - } + break; + case COMPUTE_END : + mComputeSizes = true; + mFirst = true; + mHandler.sendEmptyMessage(NEXT_LOAD_STEP); break; case REMOVE_PKG: if(localLOGV) Log.i(TAG, "Message REMOVE_PKG"); @@ -362,9 +353,9 @@ public class ManageApplications extends ListActivity implements mAppInfoAdapter.addToList(pkgName, ps); break; case REFRESH_APP_RESOURCE: - AppInfo aInfo = (AppInfo) msg.obj; + AppInfo aInfo = (AppInfo) msg.obj; if(aInfo == null) { - Log.w(TAG, "Error loading icons for applications"); + Log.w(TAG, "Error loading resources"); } else { mAppInfoAdapter.updateAppsResourceInfo(aInfo); } @@ -399,7 +390,7 @@ public class ManageApplications extends ListActivity implements // Create list view from the adapter here. Wait till the sort order // of list is defined. its either by label or by size. so atleast one of the // first steps should be complete before filling the list - mAppInfoAdapter.sortList(mSortOrder); + mAppInfoAdapter.sortBaseList(mSortOrder); if (mJustCreated) { // Set the adapter here. mJustCreated = false; @@ -419,6 +410,87 @@ public class ManageApplications extends ListActivity implements } }; + class SizeObserver extends IPackageStatsObserver.Stub { + private int mMsgId; + private CountDownLatch mCount; + + SizeObserver(int msgId) { + mMsgId = msgId; + } + + public void invokeGetSize(String packageName, CountDownLatch count) { + mCount = count; + mPm.getPackageSizeInfo(packageName, this); + } + + public void onGetStatsCompleted(PackageStats pStats, boolean pSucceeded) { + AppInfo appInfo = null; + Bundle data = new Bundle(); + data.putString(ATTR_PKG_NAME, pStats.packageName); + if(pSucceeded && pStats != null) { + if (localLOGV) Log.i(TAG, "onGetStatsCompleted::"+pStats.packageName+", ("+ + pStats.cacheSize+","+ + pStats.codeSize+", "+pStats.dataSize); + data.putParcelable(ATTR_APP_PKG_STATS, pStats); + } else { + Log.w(TAG, "Invalid package stats from PackageManager"); + } + //post message to Handler + Message msg = mHandler.obtainMessage(mMsgId, data); + msg.setData(data); + mHandler.sendMessage(msg); + mCount.countDown(); + } + } + + class TaskRunner extends Thread { + private List mPkgList; + private SizeObserver mSizeObserver; + private static final int END_MSG = COMPUTE_END; + private static final int mMsgId = COMPUTE_PKG_SIZE_DONE; + volatile boolean abort = false; + + TaskRunner(List appList) { + mPkgList = appList; + mSizeObserver = new SizeObserver(mMsgId); + start(); + } + + public void setAbort() { + abort = true; + } + + public void run() { + long startTime; + if (DEBUG_SIZE || DEBUG_TIME) { + startTime = SystemClock.elapsedRealtime(); + } + int size = mPkgList.size(); + for (int i = 0; i < size; i++) { + if (abort) { + // Exit if abort has been set. + break; + } + CountDownLatch count = new CountDownLatch(1); + String packageName = mPkgList.get(i).packageName; + long startPkgTime; + if (DEBUG_SIZE) { + startPkgTime = SystemClock.elapsedRealtime(); + } + mSizeObserver.invokeGetSize(packageName, count); + try { + count.await(); + } catch (InterruptedException e) { + Log.i(TAG, "Failed computing size for pkg : "+packageName); + } + if (DEBUG_SIZE) Log.i(TAG, "Took "+(SystemClock.elapsedRealtime() - startPkgTime) + + " ms to compute size for pkg : "+packageName); + } + if (DEBUG_SIZE || DEBUG_TIME) Log.i(TAG, "Took "+ (SystemClock.elapsedRealtime() - startTime)+ " ms to compute resources " ); + mHandler.sendEmptyMessage(END_MSG); + } + } + /* * This method compares the current cache against a new list of * installed applications and tries to update the list with add or remove @@ -587,7 +659,6 @@ public class ManageApplications extends ListActivity implements // some initialization code used when kicking off the size computation private void initAppList(List appList, int filterOption) { setProgressBarIndeterminateVisibility(true); - mComputeIndex = 0; mComputeSizes = false; mLoadLabels = false; // Initialize lists @@ -597,20 +668,25 @@ public class ManageApplications extends ListActivity implements // Utility method to start a thread to read application labels and icons private void initResourceThread() { - //load resources now - if(mResourceThread.isAlive()) { - mResourceThread.interrupt(); - mResourceThread = new ResourceLoaderThread(); + if ((mResourceThread != null) && mResourceThread.isAlive()) { + mResourceThread.setAbort(); + } + mResourceThread = new ResourceLoaderThread(); + List appList = mAppInfoAdapter.getBaseAppList(); + if ((appList != null) && (appList.size()) > 0) { + mResourceThread.loadAllResources(appList); } - mResourceThread.loadAllResources(mAppInfoAdapter.getAppList()); } private void initComputeSizes() { - // initiate compute pkg sizes + // Initiate compute package sizes if (localLOGV) Log.i(TAG, "Initiating compute sizes for first time"); - if (mAppInfoAdapter.getCount() > 0) { - mObserver.invokeGetSizeInfo(mAppInfoAdapter.getApplicationInfo(0), - COMPUTE_PKG_SIZE_DONE); + if ((mSizeComputor != null) && (mSizeComputor.isAlive())) { + mSizeComputor.setAbort(); + } + List appList = mAppInfoAdapter.getBaseAppList(); + if ((appList != null) && (appList.size()) > 0) { + mSizeComputor = new TaskRunner(appList); } else { mComputeSizes = true; } @@ -640,27 +716,55 @@ public class ManageApplications extends ListActivity implements class ResourceLoaderThread extends Thread { List mAppList; + volatile boolean abort = false; + public void setAbort() { + abort = true; + } void loadAllResources(List appList) { mAppList = appList; start(); } public void run() { - Map iconMap = new HashMap(); - if(mAppList == null || mAppList.size() <= 0) { + long start; + if (DEBUG_TIME) { + start = SystemClock.elapsedRealtime(); + } + int imax; + if(mAppList == null || (imax = mAppList.size()) <= 0) { Log.w(TAG, "Empty or null application list"); } else { - for (ApplicationInfo appInfo : mAppList) { + for (int i = 0; i < imax; i++) { + if (abort) { + return; + } + ApplicationInfo appInfo = mAppList.get(i); CharSequence appName = appInfo.loadLabel(mPm); - Drawable appIcon = appInfo.loadIcon(mPm); Message msg = mHandler.obtainMessage(REFRESH_APP_RESOURCE); - msg.obj = new AppInfo(appInfo.packageName, appName, appIcon); + msg.obj = new AppInfo(appInfo.packageName, appName, null); mHandler.sendMessage(msg); } + Message doneMsg = mHandler.obtainMessage(REFRESH_DONE); + mHandler.sendMessage(doneMsg); + if (DEBUG_TIME) Log.i(TAG, "Took "+(SystemClock.elapsedRealtime()-start)+" ms to load app labels"); + long startIcons; + if (DEBUG_TIME) { + startIcons = SystemClock.elapsedRealtime(); + } + for (int i = (imax-1); i >= 0; i--) { + if (abort) { + return; + } + ApplicationInfo appInfo = mAppList.get(i); + Drawable appIcon = appInfo.loadIcon(mPm); + Message msg = mHandler.obtainMessage(REFRESH_APP_RESOURCE); + msg.obj = new AppInfo(appInfo.packageName, null, appIcon); + mHandler.sendMessage(msg); + } + if (DEBUG_TIME) Log.i(TAG, "Took "+(SystemClock.elapsedRealtime()-startIcons)+" ms to load app icons"); } - Message doneMsg = mHandler.obtainMessage(REFRESH_DONE); - mHandler.sendMessage(doneMsg); + if (DEBUG_TIME) Log.i(TAG, "Took "+(SystemClock.elapsedRealtime()-start)+" ms to load app resources"); } } @@ -674,12 +778,18 @@ public class ManageApplications extends ListActivity implements public Drawable appIcon; public CharSequence appSize; public PackageStats appStats; - - public void refreshIcon(AppInfo pInfo) { - appName = pInfo.appName; - appIcon = pInfo.appIcon; - } + public void refreshIcon(AppInfo pInfo) { + if (pInfo == null) { + return; + } + if (pInfo.appName != null) { + appName = pInfo.appName; + } + if (pInfo.appIcon != null) { + appIcon = pInfo.appIcon; + } + } public AppInfo(String pName, CharSequence aName, Drawable aIcon) { index = -1; pkgName = pName; @@ -770,12 +880,12 @@ public class ManageApplications extends ListActivity implements } else { mAppList = appList; } - mAppLocalList = getFilteredApps(appList, filterOption); - int sortOrder = SORT_ORDER_ALPHA; if (mAppPropCache != null) { // Retain previous sort order - sortOrder = mSortOrder; + int sortOrder = mSortOrder; mAppPropMap = mAppPropCache; + // TODO is this required? + sortAppList(mAppList, sortOrder); } else { // Recreate property map mAppPropMap = new TreeMap(); @@ -783,8 +893,8 @@ public class ManageApplications extends ListActivity implements // Re init the comparators mAlphaComparator = null; mSizeComparator = null; - - sortAppList(sortOrder); + + mAppLocalList = getFilteredApps(appList, filterOption); int imax = appList.size(); for (int i = 0; i < imax; i++) { ApplicationInfo info = appList.get(i); @@ -802,7 +912,7 @@ public class ManageApplications extends ListActivity implements } public AppInfoAdapter(Context c, List appList) { - initMapFromList(appList, mFilterApps); + mAppList = appList; } public int getCount() { @@ -849,8 +959,8 @@ public class ManageApplications extends ListActivity implements return mAppPropMap.get(mAppLocalList.get(position).packageName).index; } - public List getAppList() { - return mAppLocalList; + public List getBaseAppList() { + return mAppList; } public View getView(int position, View convertView, ViewGroup parent) { @@ -908,13 +1018,20 @@ public class ManageApplications extends ListActivity implements } } - public void sortAppList(int sortOrder) { - Collections.sort(mAppLocalList, getAppComparator(sortOrder)); + public void sortAppList(List appList, int sortOrder) { + Collections.sort(appList, getAppComparator(sortOrder)); + } + + public void sortBaseList(int sortOrder) { + if (localLOGV) Log.i(TAG, "Sorting base list based on sortOrder = "+sortOrder); + sortAppList(mAppList, sortOrder); + mAppLocalList = getFilteredApps(mAppList, mFilterApps); + adjustIndex(); } public void sortList(int sortOrder) { if (localLOGV) Log.i(TAG, "sortOrder = "+sortOrder); - sortAppList(sortOrder); + sortAppList(mAppLocalList, sortOrder); adjustIndex(); notifyDataSetChanged(); } @@ -963,40 +1080,9 @@ public class ManageApplications extends ListActivity implements } return mSizeComparator; } - - /* - * This method updates resource information in the package map. - * - * @param iconMap a map of package names and attributes - * @return A boolean value to indicate if the property map has to be - * refreshed completely - */ - public boolean updateAppsResourceInfo(Map iconMap) { - if(iconMap == null) { - Log.w(TAG, "Null iconMap when refreshing icon in List Adapter"); - return true; - } - boolean changed = false; - for (ApplicationInfo info : mAppList) { - AppInfo pInfo = iconMap.get(info.packageName); - if(pInfo != null) { - AppInfo aInfo = mAppPropMap.get(info.packageName); - if (aInfo != null) { - aInfo.refreshIcon(pInfo); - } else { - return false; - } - changed = true; - } - } - if(changed) { - notifyDataSetChanged(); - } - return true; - } public boolean updateAppsResourceInfo(AppInfo pInfo) { - if(pInfo == null) { + if((pInfo == null) || (pInfo.pkgName == null)) { Log.w(TAG, "Null info when refreshing icon in List Adapter"); return false; } @@ -1192,6 +1278,10 @@ public class ManageApplications extends ListActivity implements mHandler.removeMessages(REORDER_LIST); mHandler.removeMessages(ADD_PKG_START); mHandler.removeMessages(ADD_PKG_DONE); + mHandler.removeMessages(REFRESH_APP_RESOURCE); + mHandler.removeMessages(REFRESH_DONE); + mHandler.removeMessages(NEXT_LOAD_STEP); + mHandler.removeMessages(COMPUTE_END); } private void sendMessageToHandler(int msgId, int arg1) { @@ -1295,8 +1385,8 @@ public class ManageApplications extends ListActivity implements @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Intent lIntent = getIntent(); - String action = lIntent.getAction(); + Intent intent = getIntent(); + String action = intent.getAction(); if (action.equals(Intent.ACTION_MANAGE_PACKAGE_STORAGE)) { mSortOrder = SORT_ORDER_SIZE; mSizesFirst = true; @@ -1343,20 +1433,23 @@ public class ManageApplications extends ListActivity implements private void showLoadingMsg() { - showDialog(DLG_LOADING); + if (DEBUG_TIME) { + mLoadTimeStart = SystemClock.elapsedRealtime(); + } + showDialog(DLG_LOADING); if(localLOGV) Log.i(TAG, "Displaying Loading message"); } private void dismissLoadingMsg() { if(localLOGV) Log.i(TAG, "Dismissing Loading message"); dismissDialog(DLG_LOADING); + if (DEBUG_TIME) Log.i(TAG, "Displayed loading message for "+ + (SystemClock.elapsedRealtime() - mLoadTimeStart)); } @Override public void onStart() { super.onStart(); - // Create a thread to load resources - mResourceThread = new ResourceLoaderThread(); // register receiver mReceiver.registerReceiver(); sendMessageToHandler(INIT_PKG_INFO); @@ -1365,6 +1458,9 @@ public class ManageApplications extends ListActivity implements @Override public void onStop() { super.onStop(); + // Stop the background threads + mResourceThread.setAbort(); + mSizeComputor.setAbort(); // clear all messages related to application list clearMessagesInHandler(); // register receiver here From 097ed6c671ed733c0967acc32e017020ede4575b Mon Sep 17 00:00:00 2001 From: Michael Chan <> Date: Tue, 24 Mar 2009 18:52:49 -0700 Subject: [PATCH 007/126] Automated import from //branches/donutburger/...@140897,140897 --- .../bluetooth/LocalBluetoothDevice.java | 88 ++++++++++++------- 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/src/com/android/settings/bluetooth/LocalBluetoothDevice.java b/src/com/android/settings/bluetooth/LocalBluetoothDevice.java index eedae936fb5..199a4225baf 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothDevice.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothDevice.java @@ -126,36 +126,7 @@ public class LocalBluetoothDevice implements Comparable { private void queueCommand(BluetoothJob job) { Log.d(TAG, workQueue.toString()); synchronized (workQueue) { - boolean processNow = false; - long now = System.currentTimeMillis(); - - Iterator it = workQueue.iterator(); - while (it.hasNext()) { - BluetoothJob existingJob = it.next(); - - // Remove any pending CONNECTS when we receive a DISCONNECT - if (job.command == BluetoothCommand.DISCONNECT) { - if (existingJob.timeSent == 0 - && existingJob.command == BluetoothCommand.CONNECT - && existingJob.device.mAddress.equals(job.device.mAddress) - && existingJob.profile == job.profile) { - it.remove(); - continue; - } - } - - // Defensive Code: Remove any job that older than a preset time. - // We never got a call back. It is better to have overlapping - // calls than to get stuck. - Log.d(TAG, "Age:" + (now - existingJob.timeSent)); - if (existingJob.timeSent != 0 - && (now - existingJob.timeSent) >= MAX_WAIT_TIME_FOR_FRAMEWORK) { - Log.w(TAG, "Timeout. Removing Job:" + existingJob.toString()); - it.remove(); - processNow = true; - continue; - } - } + boolean processNow = pruneQueue(job); // Add job to queue Log.d(TAG, "Adding: " + job.toString()); @@ -171,6 +142,40 @@ public class LocalBluetoothDevice implements Comparable { } } } + + private boolean pruneQueue(BluetoothJob job) { + boolean removedStaleItems = false; + long now = System.currentTimeMillis(); + Iterator it = workQueue.iterator(); + while (it.hasNext()) { + BluetoothJob existingJob = it.next(); + + // Remove any pending CONNECTS when we receive a DISCONNECT + if (job != null && job.command == BluetoothCommand.DISCONNECT) { + if (existingJob.timeSent == 0 + && existingJob.command == BluetoothCommand.CONNECT + && existingJob.device.mAddress.equals(job.device.mAddress) + && existingJob.profile == job.profile) { + Log.d(TAG, "Removed because of a pending disconnect. " + existingJob); + it.remove(); + continue; + } + } + + // Defensive Code: Remove any job that older than a preset time. + // We never got a call back. It is better to have overlapping + // calls than to get stuck. + Log.d(TAG, "Age:" + (now - existingJob.timeSent)); + if (existingJob.timeSent != 0 + && (now - existingJob.timeSent) >= MAX_WAIT_TIME_FOR_FRAMEWORK) { + Log.w(TAG, "Timeout. Removing Job:" + existingJob.toString()); + it.remove(); + removedStaleItems = true; + continue; + } + } + return removedStaleItems; + } private boolean processCommand(BluetoothJob job) { boolean successful = false; @@ -199,15 +204,29 @@ public class LocalBluetoothDevice implements Comparable { } public void onProfileStateChanged() { - // Remove the first item and process the next one - BluetoothJob job = workQueue.poll(); + Log.d(TAG, "onProfileStateChanged:" + workQueue.toString()); + BluetoothJob job = workQueue.peek(); if (job == null) { - Log.w(TAG, "Yikes, onProfileStateChanged called but job queue is empty"); + Log.v(TAG, "Yikes, onProfileStateChanged called but job queue is empty. " + + "(Okay for device initiated actions and BluetoothA2dpService initiated " + + "Auto-connections)"); + return; } else if (job.device.mAddress != mAddress) { - Log.w(TAG, "Yikes, onProfileStateChanged called but the address differ. this.mAddress=" + // This can happen in 2 cases: 1) BT device initiated pairing and + // 2) disconnects of one headset that's triggered by connects of + // another. + Log.v(TAG, "onProfileStateChanged called. The addresses differ. this.mAddress=" + mAddress + " workQueue.head=" + job.toString()); + + // Check to see if we need to remove the stale items from the queue + if (!pruneQueue(null)) { + // nothing in the queue was modify. Just ignore the notification and return. + return; + } } else { + // Remove the first item and process the next one Log.d(TAG, "LocalBluetoothDevice.onProfileStateChanged() called. MAC addr matched"); + workQueue.poll(); } processCommands(); @@ -221,6 +240,7 @@ public class LocalBluetoothDevice implements Comparable { * notification when it finishes processing a command */ private void processCommands() { + Log.d(TAG, "processCommands:" + workQueue.toString()); Iterator it = workQueue.iterator(); while (it.hasNext()) { BluetoothJob job = it.next(); From b2d3e6047805691e20925a8453ef91bbde6db9f6 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn <> Date: Tue, 24 Mar 2009 19:15:15 -0700 Subject: [PATCH 008/126] Automated import from //branches/donutburger/...@141018,141018 --- res/layout/installed_app_details.xml | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/res/layout/installed_app_details.xml b/res/layout/installed_app_details.xml index 4c06f99415f..7c8a672608f 100644 --- a/res/layout/installed_app_details.xml +++ b/res/layout/installed_app_details.xml @@ -265,6 +265,24 @@ android:layout_height="wrap_content" /> + + + + +