Merge "Add MODE_MULTI_PROCESS flag to Context.getSharedPreferences()"

This commit is contained in:
Brad Fitzpatrick
2010-12-14 16:28:33 -08:00
committed by Android (Google) Code Review
6 changed files with 117 additions and 19 deletions

View File

@@ -48156,6 +48156,17 @@
visibility="public"
>
</field>
<field name="MODE_MULTI_PROCESS"
type="int"
transient="false"
volatile="false"
value="4"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
<field name="MODE_PRIVATE"
type="int"
transient="false"

View File

@@ -554,10 +554,13 @@ class ContextImpl extends Context {
return sp;
}
}
// If somebody else (some other process) changed the prefs
// file behind our back, we reload it. This has been the
// historical (if undocumented) behavior.
sp.startReloadIfChangedUnexpectedly();
if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
// If somebody else (some other process) changed the prefs
// file behind our back, we reload it. This has been the
// historical (if undocumented) behavior.
sp.startReloadIfChangedUnexpectedly();
}
return sp;
}

View File

@@ -79,6 +79,25 @@ public abstract class Context {
*/
public static final int MODE_APPEND = 0x8000;
/**
* SharedPreference loading flag: when set, the file on disk will
* be checked for modification even if the shared preferences
* instance is already loaded in this process. This behavior is
* sometimes desired in cases where the application has multiple
* processes, all writing to the same SharedPreferences file.
* Generally there are better forms of communication between
* processes, though.
*
* <p>This was the legacy (but undocumented) behavior in and
* before Gingerbread (Android 2.3) and this flag is implied when
* targetting such releases. For applications targetting SDK
* versions <em>greater than</em> Android 2.3, this flag must be
* explicitly set if desired.
*
* @see #getSharedPreferences
*/
public static final int MODE_MULTI_PROCESS = 0x0004;
/**
* Flag for {@link #bindService}: automatically create the service as long
* as the binding exists. Note that while this will create the service,
@@ -318,7 +337,11 @@ public abstract class Context {
* editor (SharedPreferences.edit()) and then commit changes (Editor.commit()).
* @param mode Operating mode. Use 0 or {@link #MODE_PRIVATE} for the
* default operation, {@link #MODE_WORLD_READABLE}
* and {@link #MODE_WORLD_WRITEABLE} to control permissions.
* and {@link #MODE_WORLD_WRITEABLE} to control permissions. The bit
* {@link #MODE_MULTI_PROCESS} can also be used if multiple processes
* are mutating the same SharedPreferences file. {@link #MODE_MULTI_PROCESS}
* is always on in apps targetting Gingerbread (Android 2.3) and below, and
* off by default in later versions.
*
* @return Returns the single SharedPreferences instance that can be used
* to retrieve and modify the preference values.
@@ -326,6 +349,7 @@ public abstract class Context {
* @see #MODE_PRIVATE
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
* @see #MODE_MULTI_PROCESS
*/
public abstract SharedPreferences getSharedPreferences(String name,
int mode);

View File

@@ -76,7 +76,12 @@ public class FileUtils
* @return true if the file exists and false if it does not exist. If you do not have
* permission to stat the file, then this method will return false.
*/
public static native boolean getFileStatus(String path, FileStatus status);
public static boolean getFileStatus(String path, FileStatus status) {
StrictMode.noteDiskRead();
return getFileStatusNative(path, status);
}
private static native boolean getFileStatusNative(String path, FileStatus status);
/** Regular expression for safe filenames: no spaces or metacharacters */
private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");

View File

@@ -669,25 +669,46 @@ public final class StrictMode {
CloseGuard.setEnabled(enabled);
}
private static class StrictModeNetworkViolation extends BlockGuard.BlockGuardPolicyException {
/**
* @hide
*/
public static class StrictModeViolation extends BlockGuard.BlockGuardPolicyException {
public StrictModeViolation(int policyState, int policyViolated, String message) {
super(policyState, policyViolated, message);
}
}
/**
* @hide
*/
public static class StrictModeNetworkViolation extends StrictModeViolation {
public StrictModeNetworkViolation(int policyMask) {
super(policyMask, DETECT_NETWORK);
super(policyMask, DETECT_NETWORK, null);
}
}
private static class StrictModeDiskReadViolation extends BlockGuard.BlockGuardPolicyException {
/**
* @hide
*/
private static class StrictModeDiskReadViolation extends StrictModeViolation {
public StrictModeDiskReadViolation(int policyMask) {
super(policyMask, DETECT_DISK_READ);
super(policyMask, DETECT_DISK_READ, null);
}
}
private static class StrictModeDiskWriteViolation extends BlockGuard.BlockGuardPolicyException {
/**
* @hide
*/
private static class StrictModeDiskWriteViolation extends StrictModeViolation {
public StrictModeDiskWriteViolation(int policyMask) {
super(policyMask, DETECT_DISK_WRITE);
super(policyMask, DETECT_DISK_WRITE, null);
}
}
private static class StrictModeCustomViolation extends BlockGuard.BlockGuardPolicyException {
/**
* @hide
*/
private static class StrictModeCustomViolation extends StrictModeViolation {
public StrictModeCustomViolation(int policyMask, String name) {
super(policyMask, DETECT_CUSTOM, name);
}
@@ -1007,9 +1028,16 @@ public final class StrictMode {
// thread, in "gather" mode. In this case, the duration
// of the violation is computed by the ultimate caller and
// its Looper, if any.
//
// Also, as a special short-cut case when the only penalty
// bit is death, we die immediately, rather than timing
// the violation's duration. This makes it convenient to
// use in unit tests too, rather than waiting on a Looper.
//
// TODO: if in gather mode, ignore Looper.myLooper() and always
// go into this immediate mode?
if (looper == null) {
if (looper == null ||
(info.policy & PENALTY_MASK) == PENALTY_DEATH) {
info.durationMillis = -1; // unknown (redundant, already set)
handleViolation(info);
return;
@@ -1179,13 +1207,16 @@ public final class StrictMode {
}
if ((info.policy & PENALTY_DEATH) != 0) {
System.err.println("StrictMode policy violation with POLICY_DEATH; shutting down.");
Process.killProcess(Process.myPid());
System.exit(10);
executeDeathPenalty(info);
}
}
}
private static void executeDeathPenalty(ViolationInfo info) {
int violationBit = parseViolationFromMessage(info.crashInfo.exceptionMessage);
throw new StrictModeViolation(info.policy, violationBit, null);
}
/**
* In the common case, as set by conditionallyEnableDebugLogging,
* we're just dropboxing any violations but not showing a dialog,
@@ -1596,6 +1627,31 @@ public final class StrictMode {
((AndroidBlockGuardPolicy) policy).onCustomSlowCall(name);
}
/**
* @hide
*/
public static void noteDiskRead() {
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
Log.d(TAG, "noteDiskRead; policy=" + policy);
if (!(policy instanceof AndroidBlockGuardPolicy)) {
// StrictMode not enabled.
return;
}
((AndroidBlockGuardPolicy) policy).onReadFromDisk();
}
/**
* @hide
*/
public static void noteDiskWrite() {
BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
if (!(policy instanceof AndroidBlockGuardPolicy)) {
// StrictMode not enabled.
return;
}
((AndroidBlockGuardPolicy) policy).onWriteToDisk();
}
/**
* Parcelable that gets sent in Binder call headers back to callers
* to report violations that happened during a cross-process call.

View File

@@ -177,7 +177,7 @@ static const JNINativeMethod methods[] = {
{"getPermissions", "(Ljava/lang/String;[I)I", (void*)android_os_FileUtils_getPermissions},
{"setUMask", "(I)I", (void*)android_os_FileUtils_setUMask},
{"getFatVolumeId", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
{"getFileStatus", "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z", (void*)android_os_FileUtils_getFileStatus},
{"getFileStatusNative", "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z", (void*)android_os_FileUtils_getFileStatus},
};
static const char* const kFileUtilsPathName = "android/os/FileUtils";
@@ -211,4 +211,3 @@ int register_android_os_FileUtils(JNIEnv* env)
}
}