Merge "Initializing LauncherAppState only on the main thread" into ub-launcher3-master
This commit is contained in:
commit
b7f52ec0d1
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue