summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/AppWidgetService.java
diff options
context:
space:
mode:
authorAdam Cohen <adamcohen@google.com>2011-10-12 15:48:13 -0700
committerAdam Cohen <adamcohen@google.com>2011-10-12 16:22:08 -0700
commit9730031f8af9f20f3e85fbb2b8925461c3980233 (patch)
tree797eca231f4473176f0ea9689845019089d49750 /services/java/com/android/server/AppWidgetService.java
parent99f36683a4f2c218d52922ae7c2a0c0b3f2890ed (diff)
downloadframeworks_base-9730031f8af9f20f3e85fbb2b8925461c3980233.zip
frameworks_base-9730031f8af9f20f3e85fbb2b8925461c3980233.tar.gz
frameworks_base-9730031f8af9f20f3e85fbb2b8925461c3980233.tar.bz2
Fixing issue where widgets file was getting blown away, issue: 5036321
Change-Id: If40a9c79f70e11eee935b2dd2614e723423ff3bf
Diffstat (limited to 'services/java/com/android/server/AppWidgetService.java')
-rw-r--r--services/java/com/android/server/AppWidgetService.java165
1 files changed, 57 insertions, 108 deletions
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index dd649e7..eb75ebc 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -16,24 +16,6 @@
package com.android.server;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.commons.logging.impl.SimpleLog;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
@@ -42,9 +24,9 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.Intent.FilterComparison;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.content.Intent.FilterComparison;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -58,7 +40,6 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
-import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -68,20 +49,37 @@ import android.util.Slog;
import android.util.TypedValue;
import android.util.Xml;
import android.widget.RemoteViews;
-import android.widget.RemoteViewsService;
import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;
+import com.android.internal.os.AtomicFile;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.widget.IRemoteViewsAdapterConnection;
import com.android.internal.widget.IRemoteViewsFactory;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
class AppWidgetService extends IAppWidgetService.Stub
{
private static final String TAG = "AppWidgetService";
private static final String SETTINGS_FILENAME = "appwidgets.xml";
- private static final String SETTINGS_TMP_FILENAME = SETTINGS_FILENAME + ".tmp";
private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes
/*
@@ -1159,70 +1157,46 @@ class AppWidgetService extends IAppWidgetService.Stub
// only call from initialization -- it assumes that the data structures are all empty
void loadStateLocked() {
- File temp = savedStateTempFile();
- File real = savedStateRealFile();
-
- // prefer the real file. If it doesn't exist, use the temp one, and then copy it to the
- // real one. if there is both a real file and a temp one, assume that the temp one isn't
- // fully written and delete it.
- if (real.exists()) {
- readStateFromFileLocked(real);
- if (temp.exists()) {
- //noinspection ResultOfMethodCallIgnored
- temp.delete();
+ AtomicFile file = savedStateFile();
+ try {
+ FileInputStream stream = file.openRead();
+ readStateFromFileLocked(stream);
+
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to close state FileInputStream " + e);
+ }
}
- } else if (temp.exists()) {
- readStateFromFileLocked(temp);
- //noinspection ResultOfMethodCallIgnored
- temp.renameTo(real);
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "Failed to read state: " + e);
}
}
-
+
void saveStateLocked() {
- File temp = savedStateTempFile();
- File real = savedStateRealFile();
-
- if (!real.exists()) {
- // If the real one doesn't exist, it's either because this is the first time
- // or because something went wrong while copying them. In this case, we can't
- // trust anything that's in temp. In order to have the loadState code not
- // use the temporary one until it's fully written, create an empty file
- // for real, which will we'll shortly delete.
- try {
- //noinspection ResultOfMethodCallIgnored
- real.createNewFile();
- } catch (IOException e) {
- // Ignore
+ AtomicFile file = savedStateFile();
+ FileOutputStream stream;
+ try {
+ stream = file.startWrite();
+ if (writeStateToFileLocked(stream)) {
+ file.finishWrite(stream);
+ } else {
+ file.failWrite(stream);
+ Slog.w(TAG, "Failed to save state, restoring backup.");
}
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed open state file for write: " + e);
}
-
- if (temp.exists()) {
- //noinspection ResultOfMethodCallIgnored
- temp.delete();
- }
-
- if (!writeStateToFileLocked(temp)) {
- Slog.w(TAG, "Failed to persist new settings");
- return;
- }
-
- //noinspection ResultOfMethodCallIgnored
- real.delete();
- //noinspection ResultOfMethodCallIgnored
- temp.renameTo(real);
}
- boolean writeStateToFileLocked(File file) {
- FileOutputStream stream = null;
+ boolean writeStateToFileLocked(FileOutputStream stream) {
int N;
try {
- stream = new FileOutputStream(file, false);
XmlSerializer out = new FastXmlSerializer();
out.setOutput(stream, "utf-8");
out.startDocument(null, true);
-
-
out.startTag(null, "gs");
int providerIndex = 0;
@@ -1264,31 +1238,17 @@ class AppWidgetService extends IAppWidgetService.Stub
out.endTag(null, "gs");
out.endDocument();
- stream.close();
return true;
} catch (IOException e) {
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException ex) {
- // Ignore
- }
- if (file.exists()) {
- //noinspection ResultOfMethodCallIgnored
- file.delete();
- }
+ Slog.w(TAG, "Failed to write state: " + e);
return false;
}
}
- void readStateFromFileLocked(File file) {
- FileInputStream stream = null;
-
+ void readStateFromFileLocked(FileInputStream stream) {
boolean success = false;
try {
- stream = new FileInputStream(file);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(stream, null);
@@ -1390,22 +1350,15 @@ class AppWidgetService extends IAppWidgetService.Stub
} while (type != XmlPullParser.END_DOCUMENT);
success = true;
} catch (NullPointerException e) {
- Slog.w(TAG, "failed parsing " + file, e);
+ Slog.w(TAG, "failed parsing " + e);
} catch (NumberFormatException e) {
- Slog.w(TAG, "failed parsing " + file, e);
+ Slog.w(TAG, "failed parsing " + e);
} catch (XmlPullParserException e) {
- Slog.w(TAG, "failed parsing " + file, e);
+ Slog.w(TAG, "failed parsing " + e);
} catch (IOException e) {
- Slog.w(TAG, "failed parsing " + file, e);
+ Slog.w(TAG, "failed parsing " + e);
} catch (IndexOutOfBoundsException e) {
- Slog.w(TAG, "failed parsing " + file, e);
- }
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException e) {
- // Ignore
+ Slog.w(TAG, "failed parsing " + e);
}
if (success) {
@@ -1416,6 +1369,8 @@ class AppWidgetService extends IAppWidgetService.Stub
}
} else {
// failed reading, clean up
+ Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");
+
mAppWidgetIds.clear();
mHosts.clear();
final int N = mInstalledProviders.size();
@@ -1425,14 +1380,8 @@ class AppWidgetService extends IAppWidgetService.Stub
}
}
- File savedStateTempFile() {
- return new File("/data/system/" + SETTINGS_TMP_FILENAME);
- //return new File(mContext.getFilesDir(), SETTINGS_FILENAME);
- }
-
- File savedStateRealFile() {
- return new File("/data/system/" + SETTINGS_FILENAME);
- //return new File(mContext.getFilesDir(), SETTINGS_TMP_FILENAME);
+ AtomicFile savedStateFile() {
+ return new AtomicFile(new File("/data/system/" + SETTINGS_FILENAME));
}
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {