am c408a5d5: Merge "Fixing issue where widgets file was getting blown away, issue: 5036321" into ics-mr0
* commit 'c408a5d5738c84160a7e9a8299c953ea638bcef4': Fixing issue where widgets file was getting blown away, issue: 5036321
This commit is contained in:
@@ -16,24 +16,6 @@
|
|||||||
|
|
||||||
package com.android.server;
|
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.AlarmManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.appwidget.AppWidgetManager;
|
import android.appwidget.AppWidgetManager;
|
||||||
@@ -42,9 +24,9 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.Intent.FilterComparison;
|
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.Intent.FilterComparison;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
@@ -58,7 +40,6 @@ import android.net.Uri;
|
|||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Process;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -68,20 +49,37 @@ import android.util.Slog;
|
|||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.util.Xml;
|
import android.util.Xml;
|
||||||
import android.widget.RemoteViews;
|
import android.widget.RemoteViews;
|
||||||
import android.widget.RemoteViewsService;
|
|
||||||
|
|
||||||
import com.android.internal.appwidget.IAppWidgetHost;
|
import com.android.internal.appwidget.IAppWidgetHost;
|
||||||
import com.android.internal.appwidget.IAppWidgetService;
|
import com.android.internal.appwidget.IAppWidgetService;
|
||||||
|
import com.android.internal.os.AtomicFile;
|
||||||
import com.android.internal.util.FastXmlSerializer;
|
import com.android.internal.util.FastXmlSerializer;
|
||||||
import com.android.internal.widget.IRemoteViewsAdapterConnection;
|
import com.android.internal.widget.IRemoteViewsAdapterConnection;
|
||||||
import com.android.internal.widget.IRemoteViewsFactory;
|
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
|
class AppWidgetService extends IAppWidgetService.Stub
|
||||||
{
|
{
|
||||||
private static final String TAG = "AppWidgetService";
|
private static final String TAG = "AppWidgetService";
|
||||||
|
|
||||||
private static final String SETTINGS_FILENAME = "appwidgets.xml";
|
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
|
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
|
// only call from initialization -- it assumes that the data structures are all empty
|
||||||
void loadStateLocked() {
|
void loadStateLocked() {
|
||||||
File temp = savedStateTempFile();
|
AtomicFile file = savedStateFile();
|
||||||
File real = savedStateRealFile();
|
try {
|
||||||
|
FileInputStream stream = file.openRead();
|
||||||
|
readStateFromFileLocked(stream);
|
||||||
|
|
||||||
// prefer the real file. If it doesn't exist, use the temp one, and then copy it to the
|
if (stream != null) {
|
||||||
// real one. if there is both a real file and a temp one, assume that the temp one isn't
|
try {
|
||||||
// fully written and delete it.
|
stream.close();
|
||||||
if (real.exists()) {
|
} catch (IOException e) {
|
||||||
readStateFromFileLocked(real);
|
Slog.w(TAG, "Failed to close state FileInputStream " + e);
|
||||||
if (temp.exists()) {
|
}
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
temp.delete();
|
|
||||||
}
|
}
|
||||||
} else if (temp.exists()) {
|
} catch (FileNotFoundException e) {
|
||||||
readStateFromFileLocked(temp);
|
Slog.w(TAG, "Failed to read state: " + e);
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
temp.renameTo(real);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveStateLocked() {
|
void saveStateLocked() {
|
||||||
File temp = savedStateTempFile();
|
AtomicFile file = savedStateFile();
|
||||||
File real = savedStateRealFile();
|
FileOutputStream stream;
|
||||||
|
try {
|
||||||
if (!real.exists()) {
|
stream = file.startWrite();
|
||||||
// If the real one doesn't exist, it's either because this is the first time
|
if (writeStateToFileLocked(stream)) {
|
||||||
// or because something went wrong while copying them. In this case, we can't
|
file.finishWrite(stream);
|
||||||
// trust anything that's in temp. In order to have the loadState code not
|
} else {
|
||||||
// use the temporary one until it's fully written, create an empty file
|
file.failWrite(stream);
|
||||||
// for real, which will we'll shortly delete.
|
Slog.w(TAG, "Failed to save state, restoring backup.");
|
||||||
try {
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
real.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
}
|
||||||
|
} 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) {
|
boolean writeStateToFileLocked(FileOutputStream stream) {
|
||||||
FileOutputStream stream = null;
|
|
||||||
int N;
|
int N;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stream = new FileOutputStream(file, false);
|
|
||||||
XmlSerializer out = new FastXmlSerializer();
|
XmlSerializer out = new FastXmlSerializer();
|
||||||
out.setOutput(stream, "utf-8");
|
out.setOutput(stream, "utf-8");
|
||||||
out.startDocument(null, true);
|
out.startDocument(null, true);
|
||||||
|
|
||||||
|
|
||||||
out.startTag(null, "gs");
|
out.startTag(null, "gs");
|
||||||
|
|
||||||
int providerIndex = 0;
|
int providerIndex = 0;
|
||||||
@@ -1264,31 +1238,17 @@ class AppWidgetService extends IAppWidgetService.Stub
|
|||||||
out.endTag(null, "gs");
|
out.endTag(null, "gs");
|
||||||
|
|
||||||
out.endDocument();
|
out.endDocument();
|
||||||
stream.close();
|
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
try {
|
Slog.w(TAG, "Failed to write state: " + e);
|
||||||
if (stream != null) {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
if (file.exists()) {
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void readStateFromFileLocked(File file) {
|
void readStateFromFileLocked(FileInputStream stream) {
|
||||||
FileInputStream stream = null;
|
|
||||||
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
stream = new FileInputStream(file);
|
|
||||||
XmlPullParser parser = Xml.newPullParser();
|
XmlPullParser parser = Xml.newPullParser();
|
||||||
parser.setInput(stream, null);
|
parser.setInput(stream, null);
|
||||||
|
|
||||||
@@ -1390,22 +1350,15 @@ class AppWidgetService extends IAppWidgetService.Stub
|
|||||||
} while (type != XmlPullParser.END_DOCUMENT);
|
} while (type != XmlPullParser.END_DOCUMENT);
|
||||||
success = true;
|
success = true;
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
Slog.w(TAG, "failed parsing " + file, e);
|
Slog.w(TAG, "failed parsing " + e);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
Slog.w(TAG, "failed parsing " + file, e);
|
Slog.w(TAG, "failed parsing " + e);
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
Slog.w(TAG, "failed parsing " + file, e);
|
Slog.w(TAG, "failed parsing " + e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Slog.w(TAG, "failed parsing " + file, e);
|
Slog.w(TAG, "failed parsing " + e);
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (IndexOutOfBoundsException e) {
|
||||||
Slog.w(TAG, "failed parsing " + file, e);
|
Slog.w(TAG, "failed parsing " + e);
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (stream != null) {
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Ignore
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -1416,6 +1369,8 @@ class AppWidgetService extends IAppWidgetService.Stub
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// failed reading, clean up
|
// failed reading, clean up
|
||||||
|
Slog.w(TAG, "Failed to read state, clearing widgets and hosts.");
|
||||||
|
|
||||||
mAppWidgetIds.clear();
|
mAppWidgetIds.clear();
|
||||||
mHosts.clear();
|
mHosts.clear();
|
||||||
final int N = mInstalledProviders.size();
|
final int N = mInstalledProviders.size();
|
||||||
@@ -1425,14 +1380,8 @@ class AppWidgetService extends IAppWidgetService.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File savedStateTempFile() {
|
AtomicFile savedStateFile() {
|
||||||
return new File("/data/system/" + SETTINGS_TMP_FILENAME);
|
return new AtomicFile(new File("/data/system/" + SETTINGS_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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||||
|
|||||||
Reference in New Issue
Block a user