Merge "Pushing state persistence to a background thread" into jb-mr1.1-dev

This commit is contained in:
Adam Cohen
2012-11-15 13:53:52 -08:00
committed by Android (Google) Code Review
2 changed files with 43 additions and 15 deletions

View File

@@ -26,6 +26,8 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
@@ -54,13 +56,19 @@ class AppWidgetService extends IAppWidgetService.Stub
Locale mLocale; Locale mLocale;
PackageManager mPackageManager; PackageManager mPackageManager;
boolean mSafeMode; boolean mSafeMode;
private final Handler mSaveStateHandler;
private final SparseArray<AppWidgetServiceImpl> mAppWidgetServices; private final SparseArray<AppWidgetServiceImpl> mAppWidgetServices;
AppWidgetService(Context context) { AppWidgetService(Context context) {
mContext = context; mContext = context;
HandlerThread handlerThread = new HandlerThread("AppWidgetService -- Save state");
handlerThread.start();
mSaveStateHandler = new Handler(handlerThread.getLooper());
mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5); mAppWidgetServices = new SparseArray<AppWidgetServiceImpl>(5);
AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0); AppWidgetServiceImpl primary = new AppWidgetServiceImpl(context, 0, mSaveStateHandler);
mAppWidgetServices.append(0, primary); mAppWidgetServices.append(0, primary);
} }
@@ -229,7 +237,7 @@ class AppWidgetService extends IAppWidgetService.Stub
if (service == null) { if (service == null) {
Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding"); Slog.i(TAG, "Unable to find AppWidgetServiceImpl for user " + userId + ", adding");
// TODO: Verify that it's a valid user // TODO: Verify that it's a valid user
service = new AppWidgetServiceImpl(mContext, userId); service = new AppWidgetServiceImpl(mContext, userId, mSaveStateHandler);
service.systemReady(mSafeMode); service.systemReady(mSafeMode);
// Assume that BOOT_COMPLETED was received, as this is a non-primary user. // Assume that BOOT_COMPLETED was received, as this is a non-primary user.
mAppWidgetServices.append(userId, service); mAppWidgetServices.append(userId, service);

View File

@@ -41,7 +41,10 @@ import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper;
import android.os.Process; import android.os.Process;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.SystemClock; import android.os.SystemClock;
@@ -180,15 +183,18 @@ class AppWidgetServiceImpl {
boolean mStateLoaded; boolean mStateLoaded;
int mMaxWidgetBitmapMemory; int mMaxWidgetBitmapMemory;
private final Handler mSaveStateHandler;
// These are for debugging only -- widgets are going missing in some rare instances // These are for debugging only -- widgets are going missing in some rare instances
ArrayList<Provider> mDeletedProviders = new ArrayList<Provider>(); ArrayList<Provider> mDeletedProviders = new ArrayList<Provider>();
ArrayList<Host> mDeletedHosts = new ArrayList<Host>(); ArrayList<Host> mDeletedHosts = new ArrayList<Host>();
AppWidgetServiceImpl(Context context, int userId) { AppWidgetServiceImpl(Context context, int userId, Handler saveStateHandler) {
mContext = context; mContext = context;
mPm = AppGlobals.getPackageManager(); mPm = AppGlobals.getPackageManager();
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUserId = userId; mUserId = userId;
mSaveStateHandler = saveStateHandler;
computeMaximumWidgetBitmapMemory(); computeMaximumWidgetBitmapMemory();
} }
@@ -236,7 +242,7 @@ class AppWidgetServiceImpl {
updateProvidersForPackageLocked(cn.getPackageName(), removedProviders); updateProvidersForPackageLocked(cn.getPackageName(), removedProviders);
} }
} }
saveStateLocked(); saveStateAsync();
} }
} }
} }
@@ -286,7 +292,7 @@ class AppWidgetServiceImpl {
providersModified |= addProvidersForPackageLocked(pkgName); providersModified |= addProvidersForPackageLocked(pkgName);
} }
} }
saveStateLocked(); saveStateAsync();
} }
} else { } else {
Bundle extras = intent.getExtras(); Bundle extras = intent.getExtras();
@@ -297,7 +303,7 @@ class AppWidgetServiceImpl {
ensureStateLoadedLocked(); ensureStateLoadedLocked();
for (String pkgName : pkgList) { for (String pkgName : pkgList) {
providersModified |= removeProvidersForPackageLocked(pkgName); providersModified |= removeProvidersForPackageLocked(pkgName);
saveStateLocked(); saveStateAsync();
} }
} }
} }
@@ -410,7 +416,7 @@ class AppWidgetServiceImpl {
private void ensureStateLoadedLocked() { private void ensureStateLoadedLocked() {
if (!mStateLoaded) { if (!mStateLoaded) {
loadAppWidgetList(); loadAppWidgetListLocked();
loadStateLocked(); loadStateLocked();
mStateLoaded = true; mStateLoaded = true;
} }
@@ -431,7 +437,7 @@ class AppWidgetServiceImpl {
host.instances.add(id); host.instances.add(id);
mAppWidgetIds.add(id); mAppWidgetIds.add(id);
saveStateLocked(); saveStateAsync();
if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId if (DBG) log("Allocating AppWidgetId for " + packageName + " host=" + hostId
+ " id=" + appWidgetId); + " id=" + appWidgetId);
return appWidgetId; return appWidgetId;
@@ -444,7 +450,7 @@ class AppWidgetServiceImpl {
AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId); AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
if (id != null) { if (id != null) {
deleteAppWidgetLocked(id); deleteAppWidgetLocked(id);
saveStateLocked(); saveStateAsync();
} }
} }
} }
@@ -456,7 +462,7 @@ class AppWidgetServiceImpl {
Host host = lookupHostLocked(callingUid, hostId); Host host = lookupHostLocked(callingUid, hostId);
if (host != null) { if (host != null) {
deleteHostLocked(host); deleteHostLocked(host);
saveStateLocked(); saveStateAsync();
} }
} }
} }
@@ -475,7 +481,7 @@ class AppWidgetServiceImpl {
} }
} }
if (changed) { if (changed) {
saveStateLocked(); saveStateAsync();
} }
} }
} }
@@ -591,7 +597,7 @@ class AppWidgetServiceImpl {
// schedule the future updates // schedule the future updates
registerForBroadcastsLocked(p, getAppWidgetIds(p)); registerForBroadcastsLocked(p, getAppWidgetIds(p));
saveStateLocked(); saveStateAsync();
} }
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
@@ -655,8 +661,8 @@ class AppWidgetServiceImpl {
} else { } else {
mPackagesWithBindWidgetPermission.remove(packageName); mPackagesWithBindWidgetPermission.remove(packageName);
} }
saveStateAsync();
} }
saveStateLocked();
} }
// Binds to a specific RemoteViewsService // Binds to a specific RemoteViewsService
@@ -893,6 +899,20 @@ class AppWidgetServiceImpl {
} }
} }
private void saveStateAsync() {
mSaveStateHandler.post(mSaveStateRunnable);
}
private final Runnable mSaveStateRunnable = new Runnable() {
@Override
public void run() {
synchronized (mAppWidgetIds) {
ensureStateLoadedLocked();
saveStateLocked();
}
}
};
public void updateAppWidgetOptions(int appWidgetId, Bundle options) { public void updateAppWidgetOptions(int appWidgetId, Bundle options) {
synchronized (mAppWidgetIds) { synchronized (mAppWidgetIds) {
options = cloneIfLocalBinder(options); options = cloneIfLocalBinder(options);
@@ -913,7 +933,7 @@ class AppWidgetServiceImpl {
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, id.options); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, id.options);
mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId)); mContext.sendBroadcastAsUser(intent, new UserHandle(mUserId));
saveStateLocked(); saveStateAsync();
} }
} }
@@ -1214,7 +1234,7 @@ class AppWidgetServiceImpl {
} }
} }
void loadAppWidgetList() { void loadAppWidgetListLocked() {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
try { try {
List<ResolveInfo> broadcastReceivers = mPm.queryIntentReceivers(intent, List<ResolveInfo> broadcastReceivers = mPm.queryIntentReceivers(intent,