Merge "Initializing LauncherAppState only on the main thread" into ub-launcher3-master

This commit is contained in:
Sunny Goyal 2017-02-14 18:02:33 +00:00 committed by Android (Google) Code Review
commit b7f52ec0d1
2 changed files with 60 additions and 47 deletions

View File

@ -16,9 +16,11 @@
package com.android.launcher3;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Looper;
import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
@ -26,31 +28,43 @@ import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.dynamicui.ExtractionUtils;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.ConfigMonitor;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.TestingUtils;
import com.android.launcher3.util.Thunk;
import java.lang.ref.WeakReference;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
public class LauncherAppState {
public static final boolean PROFILE_STARTUP = ProviderConfig.IS_DOGFOOD_BUILD;
@Thunk final LauncherModel mModel;
private final IconCache mIconCache;
private final WidgetPreviewLoader mWidgetCache;
private static WeakReference<LauncherProvider> sLauncherProvider;
private static Context sContext;
// We do not need any synchronization for this variable as its only written on UI thread.
private static LauncherAppState INSTANCE;
private InvariantDeviceProfile mInvariantDeviceProfile;
private final Context mContext;
private final LauncherModel mModel;
private final IconCache mIconCache;
private final WidgetPreviewLoader mWidgetCache;
private final InvariantDeviceProfile mInvariantDeviceProfile;
public static LauncherAppState getInstance(Context context) {
public static LauncherAppState getInstance(final Context context) {
if (INSTANCE == null) {
INSTANCE = new LauncherAppState();
if (Looper.myLooper() == Looper.getMainLooper()) {
INSTANCE = new LauncherAppState(context.getApplicationContext());
} else {
try {
return new MainThreadExecutor().submit(new Callable<LauncherAppState>() {
@Override
public LauncherAppState call() throws Exception {
return LauncherAppState.getInstance(context);
}
}).get();
} catch (InterruptedException|ExecutionException e) {
throw new RuntimeException(e);
}
}
}
return INSTANCE;
}
@ -60,42 +74,30 @@ public class LauncherAppState {
}
public Context getContext() {
return sContext;
return mContext;
}
static void setLauncherProvider(LauncherProvider provider) {
if (sLauncherProvider != null) {
Log.w(Launcher.TAG, "setLauncherProvider called twice! old=" +
sLauncherProvider.get() + " new=" + provider);
private LauncherAppState(Context context) {
if (getLocalProvider(context) == null) {
throw new RuntimeException(
"Initializing LauncherAppState in the absence of LauncherProvider");
}
sLauncherProvider = new WeakReference<>(provider);
// The content provider exists for the entire duration of the launcher main process and
// is the first component to get created. Initializing application context here ensures
// that LauncherAppState always exists in the main process.
sContext = provider.getContext().getApplicationContext();
FileLog.setDir(sContext.getFilesDir());
}
private LauncherAppState() {
if (sContext == null) {
throw new IllegalStateException("LauncherAppState initiated before app context set");
}
Log.v(Launcher.TAG, "LauncherAppState initiated");
Preconditions.assertUIThread();
mContext = context;
if (TestingUtils.MEMORY_DUMP_ENABLED) {
TestingUtils.startTrackingMemory(sContext);
TestingUtils.startTrackingMemory(mContext);
}
mInvariantDeviceProfile = new InvariantDeviceProfile(sContext);
mIconCache = new IconCache(sContext, mInvariantDeviceProfile);
mWidgetCache = new WidgetPreviewLoader(sContext, mIconCache);
mInvariantDeviceProfile = new InvariantDeviceProfile(mContext);
mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
mModel = new LauncherModel(this, mIconCache,
Utilities.getOverrideObject(AppFilter.class, sContext, R.string.app_filter_class));
Utilities.getOverrideObject(AppFilter.class, mContext, R.string.app_filter_class));
LauncherAppsCompat.getInstance(sContext).addOnAppsChangedCallback(mModel);
LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel);
// Register intent receivers
IntentFilter filter = new IntentFilter();
@ -112,21 +114,21 @@ public class LauncherAppState {
filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
}
sContext.registerReceiver(mModel, filter);
UserManagerCompat.getInstance(sContext).enableAndResetCache();
new ConfigMonitor(sContext).register();
mContext.registerReceiver(mModel, filter);
UserManagerCompat.getInstance(mContext).enableAndResetCache();
new ConfigMonitor(mContext).register();
ExtractionUtils.startColorExtractionServiceIfNecessary(sContext);
ExtractionUtils.startColorExtractionServiceIfNecessary(mContext);
}
/**
* Call from Application.onTerminate(), which is not guaranteed to ever be called.
*/
public void onTerminate() {
sContext.unregisterReceiver(mModel);
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
mContext.unregisterReceiver(mModel);
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
launcherApps.removeOnAppsChangedCallback(mModel);
PackageInstallerCompat.getInstance(sContext).onStop();
PackageInstallerCompat.getInstance(mContext).onStop();
}
/**
@ -139,7 +141,7 @@ public class LauncherAppState {
}
LauncherModel setLauncher(Launcher launcher) {
sLauncherProvider.get().setLauncherProviderChangeListener(launcher);
getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher);
return mModel;
}
@ -166,4 +168,11 @@ public class LauncherAppState {
public static InvariantDeviceProfile getIDP(Context context) {
return LauncherAppState.getInstance(context).getInvariantDeviceProfile();
}
private static LauncherProvider getLocalProvider(Context context) {
try (ContentProviderClient cl = context.getContentResolver()
.acquireContentProviderClient(LauncherProvider.AUTHORITY)) {
return (LauncherProvider) cl.getLocalContentProvider();
}
}
}

View File

@ -55,6 +55,7 @@ import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.dynamicui.ExtractionUtils;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.util.ManagedProfileHeuristic;
@ -91,7 +92,10 @@ public class LauncherProvider extends ContentProvider {
}
mListenerHandler = new Handler(mListenerWrapper);
LauncherAppState.setLauncherProvider(this);
// The content provider exists for the entire duration of the launcher main process and
// is the first component to get created. Initializing FileLog here ensures that it's
// always available in the main process.
FileLog.setDir(getContext().getApplicationContext().getFilesDir());
return true;
}