Speed up shortcut launch performance
Apparently the framework first needs to starts the contacts provider just to
resolve the content-type for a shortcut, which is a heavy process involving
a lot of disk I/O.
Remove this by pre-setting the content type to shortcuts.
This will improve the shortcut launch performance from roughly 3.45 seconds to
2.35 seconds on a prime with a test contact in extreme cases, i.e. after:
adb shell kill `pid acore` `pid contacts` ; \
adb shell "sync; echo 3 > /proc/sys/vm/drop_caches"
Also pre-start the provider in Application.onCreate() in order to maximize
the overlap between the app initialization and the provider initialization.
This may or may not help the regular app launch performance too.
Bug 6434853
Bug 6476832
Change-Id: Ia8dcd877dcda2cac562bec18442d7fc019a08ad2
diff --git a/src/com/android/contacts/ContactsApplication.java b/src/com/android/contacts/ContactsApplication.java
index b23dde1..956ce65 100644
--- a/src/com/android/contacts/ContactsApplication.java
+++ b/src/com/android/contacts/ContactsApplication.java
@@ -26,10 +26,13 @@
import android.app.FragmentManager;
import android.app.LoaderManager;
import android.content.ContentResolver;
+import android.content.ContentUris;
import android.content.Context;
import android.content.SharedPreferences;
+import android.os.AsyncTask;
import android.os.StrictMode;
import android.preference.PreferenceManager;
+import android.provider.ContactsContract.Contacts;
import android.util.Log;
public final class ContactsApplication extends Application {
@@ -120,10 +123,6 @@
Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate start");
}
- // Priming caches to placate the StrictMode police
- Context context = getApplicationContext();
- PreferenceManager.getDefaultSharedPreferences(context);
- AccountTypeManager.getInstance(context);
if (ENABLE_FRAGMENT_LOG) FragmentManager.enableDebugLogging(true);
if (ENABLE_LOADER_LOG) LoaderManager.enableDebugLogging(true);
@@ -132,8 +131,30 @@
new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
}
+ // Perform the initialization that doesn't have to finish immediately.
+ // We use an async task here just to avoid creating a new thread.
+ (new DelayedInitializer()).execute();
+
if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
Log.d(Constants.PERFORMANCE_TAG, "ContactsApplication.onCreate finish");
}
}
+
+ private class DelayedInitializer extends AsyncTask<Void, Void, Void> {
+ @Override
+ protected Void doInBackground(Void... params) {
+ final Context context = ContactsApplication.this;
+
+ // Warm up the preferences, the account type manager and the contacts provider.
+ PreferenceManager.getDefaultSharedPreferences(context);
+ AccountTypeManager.getInstance(context);
+ getContentResolver().getType(ContentUris.withAppendedId(Contacts.CONTENT_URI, 1));
+ return null;
+ }
+
+ public void execute() {
+ executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
+ (Void[]) null);
+ }
+ }
}
diff --git a/src/com/android/contacts/list/ShortcutIntentBuilder.java b/src/com/android/contacts/list/ShortcutIntentBuilder.java
index 753ba02..d71a0f5 100644
--- a/src/com/android/contacts/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/list/ShortcutIntentBuilder.java
@@ -137,6 +137,7 @@
*/
private abstract class LoadingAsyncTask extends AsyncTask<Void, Void, Void> {
protected Uri mUri;
+ protected String mContentType;
protected String mDisplayName;
protected byte[] mBitmapData;
protected long mPhotoId;
@@ -147,6 +148,7 @@
@Override
protected Void doInBackground(Void... params) {
+ mContentType = mContext.getContentResolver().getType(mUri);
loadData();
loadPhoto();
return null;
@@ -196,7 +198,7 @@
}
@Override
protected void onPostExecute(Void result) {
- createContactShortcutIntent(mUri, mDisplayName, mBitmapData);
+ createContactShortcutIntent(mUri, mContentType, mDisplayName, mBitmapData);
}
}
@@ -248,7 +250,7 @@
return bitmap;
}
- private void createContactShortcutIntent(Uri contactUri, String displayName,
+ private void createContactShortcutIntent(Uri contactUri, String contentType, String displayName,
byte[] bitmapData) {
Bitmap bitmap = getPhotoBitmap(bitmapData);
@@ -263,7 +265,7 @@
// Tell the launcher to not do its animation, because we are doing our own
shortcutIntent.putExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION, true);
- shortcutIntent.setData(contactUri);
+ shortcutIntent.setDataAndType(contactUri, contentType);
shortcutIntent.putExtra(ContactsContract.QuickContact.EXTRA_MODE,
ContactsContract.QuickContact.MODE_LARGE);
shortcutIntent.putExtra(ContactsContract.QuickContact.EXTRA_EXCLUDE_MIMES,
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 5fe34e0..eb5fb23 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -21,6 +21,7 @@
import com.android.contacts.R;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.DataKind;
+import com.android.contacts.util.Constants;
import com.android.contacts.util.DataStatus;
import com.android.contacts.util.ImageViewDrawableSetter;
import com.android.contacts.util.SchedulingUtils;
@@ -494,6 +495,9 @@
bindData(data);
if (TRACE_LAUNCH) android.os.Debug.stopMethodTracing();
+ if (Log.isLoggable(Constants.PERFORMANCE_TAG, Log.DEBUG)) {
+ Log.d(Constants.PERFORMANCE_TAG, "QuickContact shown");
+ }
// Data bound and ready, pull curtain to show. Put this on the Handler to ensure
// that the layout passes are completed