Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc0a89fd authored by Makoto Onuki's avatar Makoto Onuki
Browse files

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
parent c8106e02
Loading
Loading
Loading
Loading
+25 −4
Original line number Diff line number Diff line
@@ -26,10 +26,13 @@ import android.app.Application;
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 @@ public final class ContactsApplication extends Application {
            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 @@ public final class ContactsApplication extends Application {
                    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);
        }
    }
}
+5 −3
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ public class ShortcutIntentBuilder {
     */
    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 @@ public class ShortcutIntentBuilder {

        @Override
        protected Void doInBackground(Void... params) {
            mContentType = mContext.getContentResolver().getType(mUri);
            loadData();
            loadPhoto();
            return null;
@@ -196,7 +198,7 @@ public class ShortcutIntentBuilder {
        }
        @Override
        protected void onPostExecute(Void result) {
            createContactShortcutIntent(mUri, mDisplayName, mBitmapData);
            createContactShortcutIntent(mUri, mContentType, mDisplayName, mBitmapData);
        }
    }

@@ -248,7 +250,7 @@ public class ShortcutIntentBuilder {
        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 @@ public class ShortcutIntentBuilder {
        // 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,
+4 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.contacts.ContactLoader;
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 @@ public class QuickContactActivity extends Activity {
            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