summaryrefslogtreecommitdiffstats
path: root/core/java/android/os
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/os')
-rw-r--r--core/java/android/os/Build.java41
-rw-r--r--core/java/android/os/INetworkManagementService.aidl3
-rw-r--r--core/java/android/os/Process.java21
-rw-r--r--core/java/android/os/RecoverySystem.java41
4 files changed, 82 insertions, 24 deletions
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 862f4c4..2df9be2 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -23,7 +23,11 @@ import com.android.internal.telephony.TelephonyProperties;
import dalvik.system.VMRuntime;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Information about the current build, extracted from system properties.
@@ -664,6 +668,7 @@ public class Build {
/** The type of build, like "user" or "eng". */
public static final String TYPE = getString("ro.build.type");
+ private static String TYPE_FOR_APPS = parseBuildTypeFromFingerprint();
/** Comma-separated tags describing the build, like "unsigned,debug". */
public static final String TAGS = getString("ro.build.tags");
@@ -690,6 +695,42 @@ public class Build {
return finger;
}
+ // Some apps like to compare the build type embedded in fingerprint
+ // to the actual build type. As the fingerprint in our case is almost
+ // always hardcoded to the stock ROM fingerprint, provide that instead
+ // of the actual one if possible.
+ private static String parseBuildTypeFromFingerprint() {
+ final String fingerprint = SystemProperties.get("ro.build.fingerprint");
+ if (TextUtils.isEmpty(fingerprint)) {
+ return null;
+ }
+ Pattern fingerprintPattern =
+ Pattern.compile("(.*)\\/(.*)\\/(.*):(.*)\\/(.*)\\/(.*):(.*)\\/(.*)");
+ Matcher matcher = fingerprintPattern.matcher(fingerprint);
+ return matcher.matches() ? matcher.group(7) : null;
+ }
+
+ /** @hide */
+ public static void adjustBuildTypeIfNeeded() {
+ if (UserHandle.isApp(Process.myUid()) && !TextUtils.isEmpty(TYPE_FOR_APPS)) {
+ try {
+ // This is sick. TYPE is final (which can't be changed because it's an API
+ // guarantee), but we have to reassign it. Resort to reflection to unset the
+ // final modifier, change the value and restore the final modifier afterwards.
+ Field typeField = Build.class.getField("TYPE");
+ Field accessFlagsField = Field.class.getDeclaredField("accessFlags");
+ accessFlagsField.setAccessible(true);
+ int currentFlags = accessFlagsField.getInt(typeField);
+ accessFlagsField.setInt(typeField, currentFlags & ~Modifier.FINAL);
+ typeField.set(null, TYPE_FOR_APPS);
+ accessFlagsField.setInt(typeField, currentFlags);
+ accessFlagsField.setAccessible(false);
+ } catch (Exception e) {
+ // shouldn't happen, but we don't want to crash the app even if it does happen
+ }
+ }
+ }
+
/**
* Ensure that raw fingerprint system property is defined. If it was derived
* dynamically by {@link #deriveFingerprint()} this is where we push the
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index cd84c8f..aa3921a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -440,4 +440,7 @@ interface INetworkManagementService
void addInterfaceToLocalNetwork(String iface, in List<RouteInfo> routes);
void removeInterfaceFromLocalNetwork(String iface);
+
+ void restrictAppOnData(int uid, boolean restrict);
+ void restrictAppOnWlan(int uid, boolean restrict);
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 65b09eb..02466cc 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -539,6 +539,15 @@ public class Process {
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
+ // Throw early if any of the arguments are malformed. This means we can
+ // avoid writing a partial response to the zygote.
+ int sz = args.size();
+ for (int i = 0; i < sz; i++) {
+ if (args.get(i).indexOf('\n') >= 0) {
+ throw new ZygoteStartFailedEx("embedded newlines not allowed");
+ }
+ }
+
/**
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
@@ -555,13 +564,8 @@ public class Process {
writer.write(Integer.toString(args.size()));
writer.newLine();
- int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
- if (arg.indexOf('\n') >= 0) {
- throw new ZygoteStartFailedEx(
- "embedded newlines not allowed");
- }
writer.write(arg);
writer.newLine();
}
@@ -570,11 +574,16 @@ public class Process {
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
+
+ // Always read the entire result from the input stream to avoid leaving
+ // bytes in the stream for future process starts to accidentally stumble
+ // upon.
result.pid = inputStream.readInt();
+ result.usingWrapper = inputStream.readBoolean();
+
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
- result.usingWrapper = inputStream.readBoolean();
return result;
} catch (IOException ex) {
zygoteState.close();
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 4b6e6c1..d277e65 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -335,22 +335,27 @@ public class RecoverySystem {
throws IOException {
String filename = packageFile.getCanonicalPath();
- FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE);
- try {
- uncryptFile.write(filename + "\n");
- } finally {
- uncryptFile.close();
- }
- // UNCRYPT_FILE needs to be readable by system server on bootup.
- if (!UNCRYPT_FILE.setReadable(true, false)) {
- Log.e(TAG, "Error setting readable for " + UNCRYPT_FILE.getCanonicalPath());
- }
- Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
+ final String cryptoStatus = SystemProperties.get("ro.crypto.state", "unsupported");
+ final boolean isEncrypted = "encrypted".equalsIgnoreCase(cryptoStatus);
- // If the package is on the /data partition, write the block map file
- // into COMMAND_FILE instead.
- if (filename.startsWith("/data/")) {
- filename = "@/cache/recovery/block.map";
+ if (isEncrypted) {
+ FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE);
+ try {
+ uncryptFile.write(filename + "\n");
+ } finally {
+ uncryptFile.close();
+ }
+ // UNCRYPT_FILE needs to be readable by system server on bootup.
+ if (!UNCRYPT_FILE.setReadable(true, false)) {
+ Log.e(TAG, "Error setting readable for " + UNCRYPT_FILE.getCanonicalPath());
+ }
+ Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
+
+ // If the package is on the /data partition, write the block map file
+ // into COMMAND_FILE instead.
+ if (filename.startsWith("/data/")) {
+ filename = "@/cache/recovery/block.map";
+ }
}
final String filenameArg = "--update_package=" + filename;
@@ -372,18 +377,18 @@ public class RecoverySystem {
* @throws SecurityException if the current user is not allowed to wipe data.
*/
public static void rebootWipeUserData(Context context) throws IOException {
- rebootWipeUserData(context, false, context.getPackageName(), false);
+ rebootWipeUserData(context, false, context.getPackageName(), true);
}
/** {@hide} */
public static void rebootWipeUserData(Context context, String reason) throws IOException {
- rebootWipeUserData(context, false, reason, false);
+ rebootWipeUserData(context, false, reason, true);
}
/** {@hide} */
public static void rebootWipeUserData(Context context, boolean shutdown)
throws IOException {
- rebootWipeUserData(context, shutdown, context.getPackageName(), false);
+ rebootWipeUserData(context, shutdown, context.getPackageName(), true);
}
/**