Merge "Throw IllegalArgumentException on invalid hex-strings."
diff --git a/Android.mk b/Android.mk
index 7cd6635..5d9c5b3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -998,13 +998,9 @@
../../external/nist-sip/java \
../../external/apache-http/src \
../../external/tagsoup/src \
- ../../external/libphonenumber/java/src
ext_src_files := $(call all-java-files-under,$(ext_dirs))
-ext_res_dirs := \
- ../../external/libphonenumber/java/src
-
# ==== the library =========================================
include $(CLEAR_VARS)
@@ -1012,7 +1008,7 @@
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVA_LIBRARIES := core-libart
-LOCAL_JAVA_RESOURCE_DIRS := $(ext_res_dirs)
+LOCAL_STATIC_JAVA_LIBRARIES := libphonenumber-platform
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := ext
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index fbdbb25..c86fd53 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -146,8 +146,10 @@
static const char kInstructionSet[] = "arm";
#elif defined(__i386__)
static const char kInstructionSet[] = "x86";
-#elif defined (__mips__)
+#elif defined (__mips__) && !defined(__LP64__)
static const char kInstructionSet[] = "mips";
+#elif defined (__mips__) && defined(__LP64__)
+ static const char kInstructionSet[] = "mips64";
#else
#error "Unknown instruction set"
#endif
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index 7b25f73..bbe6eef2 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -146,13 +146,13 @@
}
char *buf = new char[uncompLen];
if (NULL == buf) {
- ALOGW("%s: failed to allocate %d byte\n", __FUNCTION__, uncompLen);
+ ALOGW("%s: failed to allocate %zd byte\n", __FUNCTION__, uncompLen);
dataMap->release();
return -1;
}
StreamingZipInflater inflater(dataMap, uncompLen);
if (inflater.read(buf, uncompLen) < 0) {
- ALOGW("%s: failed to inflate %d byte\n", __FUNCTION__, uncompLen);
+ ALOGW("%s: failed to inflate %zd byte\n", __FUNCTION__, uncompLen);
delete[] buf;
dataMap->release();
return -1;
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 5e9d8f7..5249065 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -563,7 +563,10 @@
if (res != 0) {
Resources r = getResources(pii);
if (r != null) {
- return r.getString(res);
+ try {
+ return r.getString(res);
+ } catch (Resources.NotFoundException e) {
+ }
}
}
return null;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 17a31f3..6233676 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4161,22 +4161,24 @@
final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
boolean hasPkgInfo = false;
if (packages != null) {
- for (int i=packages.length-1; i>=0; i--) {
- //Slog.i(TAG, "Cleaning old package: " + packages[i]);
- if (!hasPkgInfo) {
- WeakReference<LoadedApk> ref;
- ref = mPackages.get(packages[i]);
- if (ref != null && ref.get() != null) {
- hasPkgInfo = true;
- } else {
- ref = mResourcePackages.get(packages[i]);
+ synchronized (mResourcesManager) {
+ for (int i=packages.length-1; i>=0; i--) {
+ //Slog.i(TAG, "Cleaning old package: " + packages[i]);
+ if (!hasPkgInfo) {
+ WeakReference<LoadedApk> ref;
+ ref = mPackages.get(packages[i]);
if (ref != null && ref.get() != null) {
hasPkgInfo = true;
+ } else {
+ ref = mResourcePackages.get(packages[i]);
+ if (ref != null && ref.get() != null) {
+ hasPkgInfo = true;
+ }
}
}
+ mPackages.remove(packages[i]);
+ mResourcePackages.remove(packages[i]);
}
- mPackages.remove(packages[i]);
- mResourcePackages.remove(packages[i]);
}
}
ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 87d785a..1b1e600 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -105,7 +105,7 @@
*/
public abstract class BackupAgent extends ContextWrapper {
private static final String TAG = "BackupAgent";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
/** @hide */
public static final int TYPE_EOF = 0;
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index a36203b..9464222 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -20,12 +20,8 @@
import java.io.FileDescriptor;
/**
- * non-standard class for creating inbound UNIX-domain socket
- * on the Android platform, this is created in the Linux non-filesystem
- * namespace.
- *
- * On simulator platforms, this may be created in a temporary directory on
- * the filesystem
+ * Non-standard class for creating an inbound UNIX-domain socket
+ * in the Linux abstract namespace.
*/
public class LocalServerSocket {
private final LocalSocketImpl impl;
@@ -35,7 +31,7 @@
private static final int LISTEN_BACKLOG = 50;
/**
- * Crewates a new server socket listening at specified name.
+ * Creates a new server socket listening at specified name.
* On the Android platform, the name is created in the Linux
* abstract namespace (instead of on the filesystem).
*
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 344dc91..9377def 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -104,7 +104,7 @@
/**
* This class is used to retrieved various statistics about the memory mappings for this
- * process. The returns info broken down by dalvik, native, and other. All results are in kB.
+ * process. The returned info is broken down by dalvik, native, and other. All results are in kB.
*/
public static class MemoryInfo implements Parcelable {
/** The proportional set size for dalvik heap. (Doesn't include other Dalvik overhead.) */
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index c5aee7b..ae95854 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -386,7 +386,7 @@
@Override
public void setClient(IPrintServiceClient client) {
- mHandler.obtainMessage(ServiceHandler.MSG_SET_CLEINT, client)
+ mHandler.obtainMessage(ServiceHandler.MSG_SET_CLIENT, client)
.sendToTarget();
}
@@ -414,7 +414,7 @@
public static final int MSG_STOP_PRINTER_STATE_TRACKING = 7;
public static final int MSG_ON_PRINTJOB_QUEUED = 8;
public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 9;
- public static final int MSG_SET_CLEINT = 10;
+ public static final int MSG_SET_CLIENT = 10;
public ServiceHandler(Looper looper) {
super(looper, null, true);
@@ -528,9 +528,9 @@
onPrintJobQueued(new PrintJob(printJobInfo, mClient));
} break;
- case MSG_SET_CLEINT: {
+ case MSG_SET_CLIENT: {
if (DEBUG) {
- Log.i(LOG_TAG, "MSG_SET_CLEINT "
+ Log.i(LOG_TAG, "MSG_SET_CLIENT "
+ getPackageName());
}
mClient = (IPrintServiceClient) message.obj;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 79e84d9..d08758b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6343,14 +6343,7 @@
public static final String CALL_AUTO_RETRY = "call_auto_retry";
/**
- * The preferred network mode 7 = Global
- * 6 = EvDo only
- * 5 = CDMA w/o EvDo
- * 4 = CDMA / EvDo auto
- * 3 = GSM / WCDMA auto
- * 2 = WCDMA only
- * 1 = GSM only
- * 0 = GSM / WCDMA preferred
+ * See RIL_PreferredNetworkType in ril.h
* @hide
*/
public static final String PREFERRED_NETWORK_MODE =
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 3301cbe..af821ba 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -62,7 +62,8 @@
// wrapper that it directly forked).
if (fdNum != 0) {
try {
- FileDescriptor fd = ZygoteInit.createFileDescriptor(fdNum);
+ FileDescriptor fd = new FileDescriptor();
+ fd.setInt$(fdNum);
DataOutputStream os = new DataOutputStream(new FileOutputStream(fd));
os.writeInt(Process.myPid());
os.close();
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 24820bc..c03938a 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -16,6 +16,11 @@
package com.android.internal.os;
+import static android.system.OsConstants.O_CLOEXEC;
+import static android.system.OsConstants.STDERR_FILENO;
+import static android.system.OsConstants.STDIN_FILENO;
+import static android.system.OsConstants.STDOUT_FILENO;
+
import android.net.Credentials;
import android.net.LocalSocket;
import android.os.Process;
@@ -186,10 +191,9 @@
}
if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
- FileDescriptor[] pipeFds = Os.pipe();
+ FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
- ZygoteInit.setCloseOnExec(serverPipeFd, true);
}
/**
@@ -224,8 +228,6 @@
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
- } catch (IOException ex) {
- logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (IllegalArgumentException ex) {
@@ -857,14 +859,15 @@
if (descriptors != null) {
try {
- ZygoteInit.reopenStdio(descriptors[0],
- descriptors[1], descriptors[2]);
+ Os.dup2(descriptors[0], STDIN_FILENO);
+ Os.dup2(descriptors[1], STDOUT_FILENO);
+ Os.dup2(descriptors[2], STDERR_FILENO);
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
newStderr = System.err;
- } catch (IOException ex) {
+ } catch (ErrnoException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}
@@ -990,8 +993,8 @@
private void setChildPgid(int pid) {
// Try to move the new child into the peer's process group.
try {
- ZygoteInit.setpgid(pid, ZygoteInit.getpgid(peer.getPid()));
- } catch (IOException ex) {
+ Os.setpgid(pid, Os.getpgid(peer.getPid()));
+ } catch (ErrnoException ex) {
// This exception is expected in the case where
// the peer is not in our session
// TODO get rid of this log message in the case where
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 62088fa..0fa9a97 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -16,6 +16,8 @@
package com.android.internal.os;
+import static android.system.OsConstants.POLLIN;
+import static android.system.OsConstants.POLLOUT;
import static android.system.OsConstants.S_IRWXG;
import static android.system.OsConstants.S_IRWXO;
@@ -32,6 +34,7 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.system.StructPollfd;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
@@ -165,8 +168,9 @@
}
try {
- sServerSocket = new LocalServerSocket(
- createFileDescriptor(fileDesc));
+ FileDescriptor fd = new FileDescriptor();
+ fd.setInt$(fileDesc);
+ sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
@@ -225,26 +229,6 @@
private static final int ROOT_UID = 0;
private static final int ROOT_GID = 0;
- /**
- * Sets effective user ID.
- */
- private static void setEffectiveUser(int uid) {
- int errno = setreuid(ROOT_UID, uid);
- if (errno != 0) {
- Log.e(TAG, "setreuid() failed. errno: " + errno);
- }
- }
-
- /**
- * Sets effective group ID.
- */
- private static void setEffectiveGroup(int gid) {
- int errno = setregid(ROOT_GID, gid);
- if (errno != 0) {
- Log.e(TAG, "setregid() failed. errno: " + errno);
- }
- }
-
static void preload() {
Log.d(TAG, "begin preload");
preloadClasses();
@@ -292,8 +276,12 @@
long startTime = SystemClock.uptimeMillis();
// Drop root perms while running static initializers.
- setEffectiveGroup(UNPRIVILEGED_GID);
- setEffectiveUser(UNPRIVILEGED_UID);
+ try {
+ Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
+ Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
+ } catch (ErrnoException ex) {
+ throw new RuntimeException("Failed to drop root", ex);
+ }
// Alter the target heap utilization. With explicit GCs this
// is not likely to have any effect.
@@ -348,8 +336,12 @@
runtime.preloadDexCaches();
// Bring back root. We'll need it later.
- setEffectiveUser(ROOT_UID);
- setEffectiveGroup(ROOT_GID);
+ try {
+ Os.setreuid(ROOT_UID, ROOT_UID);
+ Os.setregid(ROOT_GID, ROOT_GID);
+ } catch (ErrnoException ex) {
+ throw new RuntimeException("Failed to restore root", ex);
+ }
}
}
@@ -698,119 +690,42 @@
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
- FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
- int index;
-
- try {
- fdArray = fds.toArray(fdArray);
- index = selectReadable(fdArray);
- } catch (IOException ex) {
- throw new RuntimeException("Error in select()", ex);
+ StructPollfd[] pollFds = new StructPollfd[fds.size()];
+ for (int i = 0; i < pollFds.length; ++i) {
+ pollFds[i] = new StructPollfd();
+ pollFds[i].fd = fds.get(i);
+ pollFds[i].events = (short) POLLIN;
}
-
- if (index < 0) {
- throw new RuntimeException("Error in select()");
- } else if (index == 0) {
- ZygoteConnection newPeer = acceptCommandPeer(abiList);
- peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
- } else {
- boolean done;
- done = peers.get(index).runOnce();
-
- if (done) {
- peers.remove(index);
- fds.remove(index);
+ try {
+ Os.poll(pollFds, -1);
+ } catch (ErrnoException ex) {
+ throw new RuntimeException("poll failed", ex);
+ }
+ for (int i = pollFds.length - 1; i >= 0; --i) {
+ if ((pollFds[i].revents & POLLIN) == 0) {
+ continue;
+ }
+ if (i == 0) {
+ ZygoteConnection newPeer = acceptCommandPeer(abiList);
+ peers.add(newPeer);
+ fds.add(newPeer.getFileDesciptor());
+ } else {
+ boolean done = peers.get(i).runOnce();
+ if (done) {
+ peers.remove(i);
+ fds.remove(i);
+ }
}
}
}
}
/**
- * The Linux syscall "setreuid()"
- * @param ruid real uid
- * @param euid effective uid
- * @return 0 on success, non-zero errno on fail
- */
- static native int setreuid(int ruid, int euid);
-
- /**
- * The Linux syscall "setregid()"
- * @param rgid real gid
- * @param egid effective gid
- * @return 0 on success, non-zero errno on fail
- */
- static native int setregid(int rgid, int egid);
-
- /**
- * Invokes the linux syscall "setpgid"
- *
- * @param pid pid to change
- * @param pgid new process group of pid
- * @return 0 on success or non-zero errno on fail
- */
- static native int setpgid(int pid, int pgid);
-
- /**
- * Invokes the linux syscall "getpgid"
- *
- * @param pid pid to query
- * @return pgid of pid in question
- * @throws IOException on error
- */
- static native int getpgid(int pid) throws IOException;
-
- /**
- * Invokes the syscall dup2() to copy the specified descriptors into
- * stdin, stdout, and stderr. The existing stdio descriptors will be
- * closed and errors during close will be ignored. The specified
- * descriptors will also remain open at their original descriptor numbers,
- * so the caller may want to close the original descriptors.
- *
- * @param in new stdin
- * @param out new stdout
- * @param err new stderr
- * @throws IOException
- */
- static native void reopenStdio(FileDescriptor in,
- FileDescriptor out, FileDescriptor err) throws IOException;
-
- /**
- * Toggles the close-on-exec flag for the specified file descriptor.
- *
- * @param fd non-null; file descriptor
- * @param flag desired close-on-exec flag state
- * @throws IOException
- */
- static native void setCloseOnExec(FileDescriptor fd, boolean flag)
- throws IOException;
-
- /**
- * Invokes select() on the provider array of file descriptors (selecting
- * for readability only). Array elements of null are ignored.
- *
- * @param fds non-null; array of readable file descriptors
- * @return index of descriptor that is now readable or -1 for empty array.
- * @throws IOException if an error occurs
- */
- static native int selectReadable(FileDescriptor[] fds) throws IOException;
-
- /**
- * Creates a file descriptor from an int fd.
- *
- * @param fd integer OS file descriptor
- * @return non-null; FileDescriptor instance
- * @throws IOException if fd is invalid
- */
- static native FileDescriptor createFileDescriptor(int fd)
- throws IOException;
-
- /**
* Class not instantiable.
*/
private ZygoteInit() {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 97e0fd3..2d54742 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -156,7 +156,6 @@
android_server_NetworkManagementSocketTagger.cpp \
android_server_Watchdog.cpp \
android_ddm_DdmHandleNativeHeap.cpp \
- com_android_internal_os_ZygoteInit.cpp \
android_backup_BackupDataInput.cpp \
android_backup_BackupDataOutput.cpp \
android_backup_FileBackupHelperBase.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 644f6a6..fb0d5d5 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -162,7 +162,6 @@
extern int register_android_opengl_classes(JNIEnv *env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
-extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env);
extern int register_android_backup_BackupDataInput(JNIEnv *env);
extern int register_android_backup_BackupDataOutput(JNIEnv *env);
extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
@@ -526,8 +525,6 @@
JavaVMInitArgs initArgs;
char propBuf[PROPERTY_VALUE_MAX];
char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];
- char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
- char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
@@ -537,8 +534,6 @@
char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
- char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
- char dalvikVmLibBuf[PROPERTY_VALUE_MAX];
char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
@@ -567,8 +562,6 @@
char langOption[sizeof("-Duser.language=") + 3];
char regionOption[sizeof("-Duser.region=") + 3];
char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
- char jitOpBuf[sizeof("-Xjitop:")-1 + PROPERTY_VALUE_MAX];
- char jitMethodBuf[sizeof("-Xjitmethod:")-1 + PROPERTY_VALUE_MAX];
char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
bool checkJni = false;
@@ -587,9 +580,6 @@
/* extended JNI checking */
addOption("-Xcheck:jni");
- /* set a cap on JNI global references */
- addOption("-Xjnigreflimit:2000");
-
/* with -Xcheck:jni, this provides a JNI function call trace */
//addOption("-verbose:jni");
}
@@ -605,30 +595,6 @@
parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");
- property_get("dalvik.vm.check-dex-sum", propBuf, "");
- if (strcmp(propBuf, "true") == 0) {
- /* perform additional DEX checksum tests */
- addOption("-Xcheckdexsum");
- }
-
- property_get("log.redirect-stdio", propBuf, "");
- if (strcmp(propBuf, "true") == 0) {
- /* convert stdout/stderr to log messages */
- addOption("-Xlog-stdio");
- }
-
- strcpy(enableAssertBuf, "-ea:");
- property_get("dalvik.vm.enableassertions", enableAssertBuf+sizeof("-ea:")-1, "");
- if (enableAssertBuf[sizeof("-ea:")-1] != '\0') {
- /* accept "all" to mean "all classes and packages" */
- if (strcmp(enableAssertBuf+sizeof("-ea:")-1, "all") == 0)
- enableAssertBuf[3] = '\0'; // truncate to "-ea"
- ALOGI("Assertions enabled: '%s'\n", enableAssertBuf);
- addOption(enableAssertBuf);
- } else {
- ALOGV("Assertions disabled\n");
- }
-
strcpy(jniOptsBuf, "-Xjniopts:");
if (parseRuntimeOption("dalvik.vm.jniopts", jniOptsBuf, "-Xjniopts:")) {
ALOGI("JNI options: '%s'\n", jniOptsBuf);
@@ -655,14 +621,6 @@
parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
- // Increase the main thread's interpreter stack size for bug 6315322.
- addOption("-XX:mainThreadStackSize=24K");
-
- // Set the max jit code cache size. Note: size of 0 will disable the JIT.
- parseRuntimeOption("dalvik.vm.jit.codecachesize",
- jitcodecachesizeOptsBuf,
- "-Xjitcodecachesize:");
-
parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
@@ -678,53 +636,6 @@
parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");
- /*
- * Enable or disable dexopt features, such as bytecode verification and
- * calculation of register maps for precise GC.
- */
- property_get("dalvik.vm.dexopt-flags", dexoptFlagsBuf, "");
- if (dexoptFlagsBuf[0] != '\0') {
- const char* opc;
- const char* val;
-
- opc = strstr(dexoptFlagsBuf, "v="); /* verification */
- if (opc != NULL) {
- switch (*(opc+2)) {
- case 'n': val = "-Xverify:none"; break;
- case 'r': val = "-Xverify:remote"; break;
- case 'a': val = "-Xverify:all"; break;
- default: val = NULL; break;
- }
-
- if (val != NULL) {
- addOption(val);
- }
- }
-
- opc = strstr(dexoptFlagsBuf, "o="); /* optimization */
- if (opc != NULL) {
- switch (*(opc+2)) {
- case 'n': val = "-Xdexopt:none"; break;
- case 'v': val = "-Xdexopt:verified"; break;
- case 'a': val = "-Xdexopt:all"; break;
- case 'f': val = "-Xdexopt:full"; break;
- default: val = NULL; break;
- }
-
- if (val != NULL) {
- addOption(val);
- }
- }
-
- opc = strstr(dexoptFlagsBuf, "m=y"); /* register map */
- if (opc != NULL) {
- addOption("-Xgenregmap");
-
- /* turn on precise GC while we're at it */
- addOption("-Xgc:precise");
- }
- }
-
/* enable debugging; set suspend=y to pause during VM init */
/* use android ADB transport */
addOption("-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y");
@@ -733,12 +644,6 @@
lockProfThresholdBuf,
"-Xlockprofthreshold:");
- /* Force interpreter-only mode for selected opcodes. Eg "1-0a,3c,f1-ff" */
- parseRuntimeOption("dalvik.vm.jit.op", jitOpBuf, "-Xjitop:");
-
- /* Force interpreter-only mode for selected methods */
- parseRuntimeOption("dalvik.vm.jit.method", jitMethodBuf, "-Xjitmethod:");
-
if (executionMode == kEMIntPortable) {
addOption("-Xint:portable");
} else if (executionMode == kEMIntFast) {
@@ -747,64 +652,57 @@
addOption("-Xint:jit");
}
- // libart tolerates libdvm flags, but not vice versa, so only pass some options if libart.
- property_get("persist.sys.dalvik.vm.lib.2", dalvikVmLibBuf, "libart.so");
- bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0);
+ // If we are booting without the real /data, don't spend time compiling.
+ property_get("vold.decrypt", voldDecryptBuf, "");
+ bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) ||
+ (strcmp(voldDecryptBuf, "1") == 0));
- if (libart) {
- // If we booting without the real /data, don't spend time compiling.
- property_get("vold.decrypt", voldDecryptBuf, "");
- bool skip_compilation = ((strcmp(voldDecryptBuf, "trigger_restart_min_framework") == 0) ||
- (strcmp(voldDecryptBuf, "1") == 0));
-
- // Extra options for boot.art/boot.oat image generation.
- parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,
- "-Xms", "-Ximage-compiler-option");
- parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,
- "-Xmx", "-Ximage-compiler-option");
- if (skip_compilation) {
- addOption("-Ximage-compiler-option");
- addOption("--compiler-filter=verify-none");
- } else {
- parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,
- "--compiler-filter=", "-Ximage-compiler-option");
- }
-
- // Make sure there is a preloaded-classes file.
- if (!hasFile("/system/etc/preloaded-classes")) {
- ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
- strerror(errno));
- goto bail;
- }
+ // Extra options for boot.art/boot.oat image generation.
+ parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xms", dex2oatXmsImageFlagsBuf,
+ "-Xms", "-Ximage-compiler-option");
+ parseCompilerRuntimeOption("dalvik.vm.image-dex2oat-Xmx", dex2oatXmxImageFlagsBuf,
+ "-Xmx", "-Ximage-compiler-option");
+ if (skip_compilation) {
addOption("-Ximage-compiler-option");
- addOption("--image-classes=/system/etc/preloaded-classes");
-
- // If there is a compiled-classes file, push it.
- if (hasFile("/system/etc/compiled-classes")) {
- addOption("-Ximage-compiler-option");
- addOption("--compiled-classes=/system/etc/compiled-classes");
- }
-
- property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
- parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
-
- // Extra options for DexClassLoader.
- parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,
- "-Xms", "-Xcompiler-option");
- parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,
- "-Xmx", "-Xcompiler-option");
- if (skip_compilation) {
- addOption("-Xcompiler-option");
- addOption("--compiler-filter=verify-none");
- } else {
- parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,
- "--compiler-filter=", "-Xcompiler-option");
- }
- property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
- parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
-
+ addOption("--compiler-filter=verify-none");
+ } else {
+ parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,
+ "--compiler-filter=", "-Ximage-compiler-option");
}
+ // Make sure there is a preloaded-classes file.
+ if (!hasFile("/system/etc/preloaded-classes")) {
+ ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
+ strerror(errno));
+ goto bail;
+ }
+ addOption("-Ximage-compiler-option");
+ addOption("--image-classes=/system/etc/preloaded-classes");
+
+ // If there is a compiled-classes file, push it.
+ if (hasFile("/system/etc/compiled-classes")) {
+ addOption("-Ximage-compiler-option");
+ addOption("--compiled-classes=/system/etc/compiled-classes");
+ }
+
+ property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
+ parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
+
+ // Extra options for DexClassLoader.
+ parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xms", dex2oatXmsFlagsBuf,
+ "-Xms", "-Xcompiler-option");
+ parseCompilerRuntimeOption("dalvik.vm.dex2oat-Xmx", dex2oatXmxFlagsBuf,
+ "-Xmx", "-Xcompiler-option");
+ if (skip_compilation) {
+ addOption("-Xcompiler-option");
+ addOption("--compiler-filter=verify-none");
+ } else {
+ parseCompilerOption("dalvik.vm.dex2oat-filter", dex2oatCompilerFilterBuf,
+ "--compiler-filter=", "-Xcompiler-option");
+ }
+ property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
+ parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
+
/* extra options; parse this late so it overrides others */
property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
parseExtraOpts(extraOptsBuf, NULL);
@@ -821,67 +719,65 @@
/*
* Set profiler options
*/
- if (libart) {
- // Whether or not the profiler should be enabled.
- property_get("dalvik.vm.profiler", propBuf, "0");
- if (propBuf[0] == '1') {
- addOption("-Xenable-profiler");
- }
+ // Whether or not the profiler should be enabled.
+ property_get("dalvik.vm.profiler", propBuf, "0");
+ if (propBuf[0] == '1') {
+ addOption("-Xenable-profiler");
+ }
- // Whether the profile should start upon app startup or be delayed by some random offset
- // (in seconds) that is bound between 0 and a fixed value.
- property_get("dalvik.vm.profile.start-immed", propBuf, "0");
- if (propBuf[0] == '1') {
- addOption("-Xprofile-start-immediately");
- }
+ // Whether the profile should start upon app startup or be delayed by some random offset
+ // (in seconds) that is bound between 0 and a fixed value.
+ property_get("dalvik.vm.profile.start-immed", propBuf, "0");
+ if (propBuf[0] == '1') {
+ addOption("-Xprofile-start-immediately");
+ }
- // Number of seconds during profile runs.
- parseRuntimeOption("dalvik.vm.profile.period-secs", profilePeriod, "-Xprofile-period:");
+ // Number of seconds during profile runs.
+ parseRuntimeOption("dalvik.vm.profile.period-secs", profilePeriod, "-Xprofile-period:");
- // Length of each profile run (seconds).
- parseRuntimeOption("dalvik.vm.profile.duration-secs",
- profileDuration,
- "-Xprofile-duration:");
+ // Length of each profile run (seconds).
+ parseRuntimeOption("dalvik.vm.profile.duration-secs",
+ profileDuration,
+ "-Xprofile-duration:");
- // Polling interval during profile run (microseconds).
- parseRuntimeOption("dalvik.vm.profile.interval-us", profileInterval, "-Xprofile-interval:");
+ // Polling interval during profile run (microseconds).
+ parseRuntimeOption("dalvik.vm.profile.interval-us", profileInterval, "-Xprofile-interval:");
- // Coefficient for period backoff. The the period is multiplied
- // by this value after each profile run.
- parseRuntimeOption("dalvik.vm.profile.backoff-coeff", profileBackoff, "-Xprofile-backoff:");
+ // Coefficient for period backoff. The the period is multiplied
+ // by this value after each profile run.
+ parseRuntimeOption("dalvik.vm.profile.backoff-coeff", profileBackoff, "-Xprofile-backoff:");
- // Top K% of samples that are considered relevant when
- // deciding if the app should be recompiled.
- parseRuntimeOption("dalvik.vm.profile.top-k-thr",
- profileTopKThreshold,
- "-Xprofile-top-k-threshold:");
+ // Top K% of samples that are considered relevant when
+ // deciding if the app should be recompiled.
+ parseRuntimeOption("dalvik.vm.profile.top-k-thr",
+ profileTopKThreshold,
+ "-Xprofile-top-k-threshold:");
- // The threshold after which a change in the structure of the
- // top K% profiled samples becomes significant and triggers
- // recompilation. A change in profile is considered
- // significant if X% (top-k-change-threshold) of the top K%
- // (top-k-threshold property) samples has changed.
- parseRuntimeOption("dalvik.vm.profile.top-k-ch-thr",
- profileTopKChangeThreshold,
- "-Xprofile-top-k-change-threshold:");
+ // The threshold after which a change in the structure of the
+ // top K% profiled samples becomes significant and triggers
+ // recompilation. A change in profile is considered
+ // significant if X% (top-k-change-threshold) of the top K%
+ // (top-k-threshold property) samples has changed.
+ parseRuntimeOption("dalvik.vm.profile.top-k-ch-thr",
+ profileTopKChangeThreshold,
+ "-Xprofile-top-k-change-threshold:");
- // Type of profile data.
- parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:");
+ // Type of profile data.
+ parseRuntimeOption("dalvik.vm.profiler.type", profileType, "-Xprofile-type:");
- // Depth of bounded stack data
- parseRuntimeOption("dalvik.vm.profile.stack-depth",
- profileMaxStackDepth,
- "-Xprofile-max-stack-depth:");
+ // Depth of bounded stack data
+ parseRuntimeOption("dalvik.vm.profile.stack-depth",
+ profileMaxStackDepth,
+ "-Xprofile-max-stack-depth:");
- // Native bridge library. "0" means that native bridge is disabled.
- property_get("ro.dalvik.vm.native.bridge", propBuf, "");
- if (propBuf[0] == '\0') {
- ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");
- } else if (strcmp(propBuf, "0") != 0) {
- snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,
- "-XX:NativeBridge=%s", propBuf);
- addOption(nativeBridgeLibrary);
- }
+ // Native bridge library. "0" means that native bridge is disabled.
+ property_get("ro.dalvik.vm.native.bridge", propBuf, "");
+ if (propBuf[0] == '\0') {
+ ALOGW("ro.dalvik.vm.native.bridge is not expected to be empty");
+ } else if (strcmp(propBuf, "0") != 0) {
+ snprintf(nativeBridgeLibrary, sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX,
+ "-XX:NativeBridge=%s", propBuf);
+ addOption(nativeBridgeLibrary);
}
initArgs.version = JNI_VERSION_1_4;
@@ -1321,7 +1217,6 @@
REG_JNI(register_android_net_NetworkUtils),
REG_JNI(register_android_net_TrafficStats),
REG_JNI(register_android_os_MemoryFile),
- REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_com_android_internal_os_Zygote),
REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
REG_JNI(register_android_hardware_Camera),
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 37f5062..43b8471 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -182,7 +182,7 @@
if (status == WOULD_BLOCK) {
if (kDebugDispatchCycle) {
- ALOGD("channel '%s' ~ Sent %u queued finish events; %u left.",
+ ALOGD("channel '%s' ~ Sent %zu queued finish events; %zu left.",
getInputChannelName(), i, mFinishQueue.size());
}
return 1; // keep the callback, try again later
@@ -201,7 +201,7 @@
}
}
if (kDebugDispatchCycle) {
- ALOGD("channel '%s' ~ Sent %u queued finish events; none left.",
+ ALOGD("channel '%s' ~ Sent %zu queued finish events; none left.",
getInputChannelName(), mFinishQueue.size());
}
mFinishQueue.clear();
@@ -218,7 +218,7 @@
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.",
- getInputChannelName(), consumeBatches ? "true" : "false", frameTime);
+ getInputChannelName(), consumeBatches ? "true" : "false", (long long)frameTime);
}
if (consumeBatches) {
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index e7388cf..265daeb 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -204,7 +204,7 @@
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Received finished signal, seq=%u, handled=%s, "
- "pendingEvents=%u.",
+ "pendingEvents=%zu.",
getInputChannelName(), seq, handled ? "true" : "false",
mPublishedSeqMap.size());
}
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
deleted file mode 100644
index 496f569..0000000
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Zygote"
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <utils/misc.h>
-#include <errno.h>
-#include <sys/select.h>
-
-#include "jni.h"
-#include <JNIHelp.h>
-#include "core_jni_helpers.h"
-
-#include <sys/capability.h>
-#include <sys/prctl.h>
-
-namespace android {
-
-/*
- * In class com.android.internal.os.ZygoteInit:
- * private static native boolean setreuid(int ruid, int euid)
- */
-static jint com_android_internal_os_ZygoteInit_setreuid(
- JNIEnv* env, jobject clazz, jint ruid, jint euid)
-{
- if (setreuid(ruid, euid) < 0) {
- return errno;
- }
- return 0;
-}
-
-/*
- * In class com.android.internal.os.ZygoteInit:
- * private static native int setregid(int rgid, int egid)
- */
-static jint com_android_internal_os_ZygoteInit_setregid(
- JNIEnv* env, jobject clazz, jint rgid, jint egid)
-{
- if (setregid(rgid, egid) < 0) {
- return errno;
- }
- return 0;
-}
-
-/*
- * In class com.android.internal.os.ZygoteInit:
- * private static native int setpgid(int rgid, int egid)
- */
-static jint com_android_internal_os_ZygoteInit_setpgid(
- JNIEnv* env, jobject clazz, jint pid, jint pgid)
-{
- if (setpgid(pid, pgid) < 0) {
- return errno;
- }
- return 0;
-}
-
-/*
- * In class com.android.internal.os.ZygoteInit:
- * private static native int getpgid(int pid)
- */
-static jint com_android_internal_os_ZygoteInit_getpgid(
- JNIEnv* env, jobject clazz, jint pid)
-{
- pid_t ret;
- ret = getpgid(pid);
-
- if (ret < 0) {
- jniThrowIOException(env, errno);
- }
-
- return ret;
-}
-
-static void com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv* env,
- jobject clazz, jobject in, jobject out, jobject errfd)
-{
- int fd;
- int err;
-
- fd = jniGetFDFromFileDescriptor(env, in);
-
- if (env->ExceptionCheck()) {
- return;
- }
-
- do {
- err = dup2(fd, STDIN_FILENO);
- } while (err < 0 && errno == EINTR);
-
- fd = jniGetFDFromFileDescriptor(env, out);
-
- if (env->ExceptionCheck()) {
- return;
- }
-
- do {
- err = dup2(fd, STDOUT_FILENO);
- } while (err < 0 && errno == EINTR);
-
- fd = jniGetFDFromFileDescriptor(env, errfd);
-
- if (env->ExceptionCheck()) {
- return;
- }
-
- do {
- err = dup2(fd, STDERR_FILENO);
- } while (err < 0 && errno == EINTR);
-}
-
-static void com_android_internal_os_ZygoteInit_setCloseOnExec (JNIEnv *env,
- jobject clazz, jobject descriptor, jboolean flag)
-{
- int fd;
- int err;
- int fdFlags;
-
- fd = jniGetFDFromFileDescriptor(env, descriptor);
-
- if (env->ExceptionCheck()) {
- return;
- }
-
- fdFlags = fcntl(fd, F_GETFD);
-
- if (fdFlags < 0) {
- jniThrowIOException(env, errno);
- return;
- }
-
- if (flag) {
- fdFlags |= FD_CLOEXEC;
- } else {
- fdFlags &= ~FD_CLOEXEC;
- }
-
- err = fcntl(fd, F_SETFD, fdFlags);
-
- if (err < 0) {
- jniThrowIOException(env, errno);
- return;
- }
-}
-
-static jint com_android_internal_os_ZygoteInit_selectReadable (
- JNIEnv *env, jobject clazz, jobjectArray fds)
-{
- if (fds == NULL) {
- jniThrowNullPointerException(env, "fds == null");
- return -1;
- }
-
- jsize length = env->GetArrayLength(fds);
- fd_set fdset;
-
- if (env->ExceptionCheck()) {
- return -1;
- }
-
- FD_ZERO(&fdset);
-
- int nfds = 0;
- for (jsize i = 0; i < length; i++) {
- jobject fdObj = env->GetObjectArrayElement(fds, i);
- if (env->ExceptionCheck()) {
- return -1;
- }
- if (fdObj == NULL) {
- continue;
- }
- int fd = jniGetFDFromFileDescriptor(env, fdObj);
- if (env->ExceptionCheck()) {
- return -1;
- }
-
- FD_SET(fd, &fdset);
-
- if (fd >= nfds) {
- nfds = fd + 1;
- }
- }
-
- int err;
- do {
- err = select (nfds, &fdset, NULL, NULL, NULL);
- } while (err < 0 && errno == EINTR);
-
- if (err < 0) {
- jniThrowIOException(env, errno);
- return -1;
- }
-
- for (jsize i = 0; i < length; i++) {
- jobject fdObj = env->GetObjectArrayElement(fds, i);
- if (env->ExceptionCheck()) {
- return -1;
- }
- if (fdObj == NULL) {
- continue;
- }
- int fd = jniGetFDFromFileDescriptor(env, fdObj);
- if (env->ExceptionCheck()) {
- return -1;
- }
- if (FD_ISSET(fd, &fdset)) {
- return (jint)i;
- }
- }
- return -1;
-}
-
-static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
- JNIEnv *env, jobject clazz, jint fd)
-{
- return jniCreateFileDescriptor(env, fd);
-}
-
-/*
- * JNI registration.
- */
-static JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "setreuid", "(II)I",
- (void*) com_android_internal_os_ZygoteInit_setreuid },
- { "setregid", "(II)I",
- (void*) com_android_internal_os_ZygoteInit_setregid },
- { "setpgid", "(II)I",
- (void *) com_android_internal_os_ZygoteInit_setpgid },
- { "getpgid", "(I)I",
- (void *) com_android_internal_os_ZygoteInit_getpgid },
- { "reopenStdio",
- "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
- "Ljava/io/FileDescriptor;)V",
- (void *) com_android_internal_os_ZygoteInit_reopenStdio},
- { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
- (void *) com_android_internal_os_ZygoteInit_setCloseOnExec},
- { "selectReadable", "([Ljava/io/FileDescriptor;)I",
- (void *) com_android_internal_os_ZygoteInit_selectReadable },
- { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
- (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
-};
-int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
-{
- return RegisterMethodsOrDie(env,
- "com/android/internal/os/ZygoteInit", gMethods, NELEM(gMethods));
-}
-
-}; // namespace android
diff --git a/core/tests/coretests/src/android/os/SELinuxTest.java b/core/tests/coretests/src/android/os/SELinuxTest.java
deleted file mode 100644
index 9b63a6b..0000000
--- a/core/tests/coretests/src/android/os/SELinuxTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package android.os;
-
-import android.os.Process;
-import android.os.SELinux;
-import android.test.AndroidTestCase;
-import static junit.framework.Assert.assertEquals;
-
-public class SELinuxTest extends AndroidTestCase {
-
- public void testgetFileCon() {
- if(SELinux.isSELinuxEnabled() == false)
- return;
-
- String ctx = SELinux.getFileContext("/system/bin/toolbox");
- assertEquals(ctx, "u:object_r:system_file:s0");
- }
-
- public void testgetCon() {
- if(SELinux.isSELinuxEnabled() == false)
- return;
-
- String mycon = SELinux.getContext();
- assertEquals(mycon, "u:r:untrusted_app:s0:c33");
- }
-
- public void testgetPidCon() {
- if(SELinux.isSELinuxEnabled() == false)
- return;
-
- String mycon = SELinux.getPidContext(Process.myPid());
- assertEquals(mycon, "u:r:untrusted_app:s0:c33");
- }
-
- public void testcheckSELinuxAccess() {
- if(SELinux.isSELinuxEnabled() == false)
- return;
-
- String mycon = SELinux.getContext();
- boolean ret;
- ret = SELinux.checkSELinuxAccess(mycon, mycon, "process", "fork");
- assertEquals(ret,"true");
- ret = SELinux.checkSELinuxAccess(mycon, mycon, "memprotect", "mmap_zero");
- assertEquals(ret,"true");
- }
-}
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 52e9910..c0795b6 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -93,7 +93,7 @@
env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
env->DeleteLocalRef(byteArrayObj);
if (env->ExceptionCheck()) {
- ALOGW("Exception occurred while reading %zu at %lld", size, offset);
+ ALOGW("Exception occurred while reading %zu at %lld", size, (long long)offset);
LOGW_EX(env);
env->ExceptionClear();
return -1;
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index dae6d3b..fc7931e 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -228,7 +228,7 @@
static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
{
- ALOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
+ ALOGV("getFrameAtTime: %lld us option: %d", (long long)timeUs, option);
MediaMetadataRetriever* retriever = getRetriever(env, thiz);
if (retriever == 0) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index f234a1b..ecb2ac8 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -107,7 +107,7 @@
if (dstSize < (offset + size)) {
ALOGE("writeSampleData saw wrong dstSize %lld, size %d, offset %d",
- dstSize, size, offset);
+ (long long)dstSize, size, offset);
if (byteArray != NULL) {
env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
}
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index ab8b4b8..914b8a6 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -305,7 +305,7 @@
android_media_MediaRecorder_setMaxFileSize(
JNIEnv *env, jobject thiz, jlong max_filesize_bytes)
{
- ALOGV("setMaxFileSize(%lld)", max_filesize_bytes);
+ ALOGV("setMaxFileSize(%lld)", (long long)max_filesize_bytes);
sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
char params[64];
diff --git a/media/mca/filterfw/Android.mk b/media/mca/filterfw/Android.mk
index a63d635..334f4e2 100644
--- a/media/mca/filterfw/Android.mk
+++ b/media/mca/filterfw/Android.mk
@@ -43,10 +43,4 @@
libjnigraphics \
libmedia
-# Don't prelink this library. For more efficient code, you may want
-# to add this library to the prelink map and set this to true. However,
-# it's difficult to do this for applications that are not supplied as
-# part of a system image.
-LOCAL_PRELINK_MODULE := false
-
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/mca/filterfw/jni/Android.mk b/media/mca/filterfw/jni/Android.mk
index 4ae32ac..cba4e7e 100644
--- a/media/mca/filterfw/jni/Android.mk
+++ b/media/mca/filterfw/jni/Android.mk
@@ -41,13 +41,6 @@
$(JNI_H_INCLUDE) \
$(LOCAL_PATH)/..
-# Don't prelink this library. For more efficient code, you may want
-# to add this library to the prelink map and set this to true. However,
-# it's difficult to do this for applications that are not supplied as
-# part of a system image.
-LOCAL_PRELINK_MODULE := false
-
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -Wno-unused-parameter
include $(BUILD_STATIC_LIBRARY)
-
diff --git a/media/mca/filterfw/native/core/shader_program.cpp b/media/mca/filterfw/native/core/shader_program.cpp
index f1ea7ed..1e573fb 100644
--- a/media/mca/filterfw/native/core/shader_program.cpp
+++ b/media/mca/filterfw/native/core/shader_program.cpp
@@ -315,7 +315,7 @@
size_t next_pos = 0;
size_t line_number = 1;
while ( (next_pos = src.find_first_of('\n', cur_pos)) != std::string::npos) {
- ALOGE("%03d : %s", line_number, src.substr(cur_pos, next_pos-cur_pos).c_str());
+ ALOGE("%03zd : %s", line_number, src.substr(cur_pos, next_pos-cur_pos).c_str());
cur_pos = next_pos + 1;
line_number++;
}
@@ -435,7 +435,7 @@
if (tex_var >= 0) {
glUniform1i(tex_var, i);
} else {
- ALOGE("ShaderProgram: Shader does not seem to support %d number of "
+ ALOGE("ShaderProgram: Shader does not seem to support %zd number of "
"inputs! Missing uniform 'tex_sampler_%d'!", textures.size(), i);
return false;
}
diff --git a/media/mca/filterpacks/Android.mk b/media/mca/filterpacks/Android.mk
index 7e8661f..0ff7658 100644
--- a/media/mca/filterpacks/Android.mk
+++ b/media/mca/filterpacks/Android.mk
@@ -48,8 +48,6 @@
LOCAL_SHARED_LIBRARIES := liblog libutils libfilterfw
-LOCAL_PRELINK_MODULE := false
-
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
include $(BUILD_SHARED_LIBRARY)
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ccc700d..1502829 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -5797,6 +5797,7 @@
if (denyTransientStatus || denyTransientNav) {
// clear the clearable flags instead
clearClearableFlagsLw();
+ vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS;
}
vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
diff --git a/preloaded-classes b/preloaded-classes
index 7686431..dee84f0 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -2631,7 +2631,6 @@
javax.microedition.khronos.opengles.GL11ExtensionPack
javax.net.DefaultSocketFactory
javax.net.SocketFactory
-javax.net.ssl.DefaultHostnameVerifier
javax.net.ssl.DistinguishedNameParser
javax.net.ssl.HostnameVerifier
javax.net.ssl.HttpsURLConnection
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 2ee4ff2..114042d 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1146,6 +1146,13 @@
mApplicationContext = ctx.getApplicationContext();
}
mRWLock = new ReentrantReadWriteLock();
+ try {
+ registerNativeAllocation.invoke(sRuntime, 4 * 1024 * 1024); // 4MB for GC sake
+ } catch (Exception e) {
+ Log.e(RenderScript.LOG_TAG, "Couldn't invoke registerNativeAllocation:" + e);
+ throw new RSRuntimeException("Couldn't invoke registerNativeAllocation:" + e);
+ }
+
}
/**
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 8b524dd..0c555c5 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1587,7 +1587,7 @@
if (mLastAlarmDeliveryTime <= 0) {
return false;
}
- if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime > nowELAPSED) {
+ if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime < nowELAPSED) {
// This is just a little paranoia, if somehow we have pending non-wakeup alarms
// and the next delivery time is in the past, then just deliver them all. This
// avoids bugs where we get stuck in a loop trying to poll for alarms.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 79f2e7c..e3f7fb3 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4874,9 +4874,11 @@
stats.noteProcessDiedLocked(app.info.uid, pid);
}
- Process.killProcessQuiet(pid);
- Process.killProcessGroup(app.info.uid, pid);
- app.killed = true;
+ if (!app.killed) {
+ Process.killProcessQuiet(pid);
+ Process.killProcessGroup(app.info.uid, pid);
+ app.killed = true;
+ }
// Clean up already done if the process has been re-started.
if (app.pid == pid && app.thread != null &&
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index df4bf28..c03dbc2 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1595,6 +1595,7 @@
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mWaitingVisibleActivities.remove(next);
+ next.waitingVisible = false;
if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
@@ -2269,7 +2270,7 @@
// In this case, we want to finish this activity
// and everything above it, so be sneaky and pretend
// like these are all in the reply chain.
- end = numActivities - 1;
+ end = activities.size() - 1;
} else if (replyChainEnd < 0) {
end = i;
} else {
@@ -2807,6 +2808,7 @@
mStackSupervisor.mStoppingActivities.remove(r);
mStackSupervisor.mGoingToSleepActivities.remove(r);
mStackSupervisor.mWaitingVisibleActivities.remove(r);
+ r.waitingVisible = false;
if (mResumedActivity == r) {
mResumedActivity = null;
}
@@ -3007,6 +3009,7 @@
// down to the max limit while they are still waiting to finish.
mStackSupervisor.mFinishingActivities.remove(r);
mStackSupervisor.mWaitingVisibleActivities.remove(r);
+ r.waitingVisible = false;
// Remove any pending results.
if (r.finishing && r.pendingResults != null) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 03dd3c0..6f5866a 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1315,7 +1315,6 @@
}
}
}
- ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
final int launchFlags = intent.getFlags();
@@ -1392,6 +1391,8 @@
}
}
+ final ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
+
if (err != ActivityManager.START_SUCCESS) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1,
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index bffb541..c5f63f1 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -445,14 +445,14 @@
mAm.mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.PACKAGE_USAGE_STATS, null);
Parcel current = Parcel.obtain();
+ synchronized (mAm) {
+ long now = SystemClock.uptimeMillis();
+ mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
+ mProcessStats.mTimePeriodEndUptime = now;
+ mProcessStats.writeToParcel(current, now, 0);
+ }
mWriteLock.lock();
try {
- synchronized (mAm) {
- long now = SystemClock.uptimeMillis();
- mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
- mProcessStats.mTimePeriodEndUptime = now;
- mProcessStats.writeToParcel(current, now, 0);
- }
if (historic != null) {
ArrayList<String> files = getCommittedFiles(0, false, true);
if (files != null) {
@@ -476,18 +476,18 @@
public ParcelFileDescriptor getStatsOverTime(long minTime) {
mAm.mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+ Parcel current = Parcel.obtain();
+ long curTime;
+ synchronized (mAm) {
+ long now = SystemClock.uptimeMillis();
+ mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
+ mProcessStats.mTimePeriodEndUptime = now;
+ mProcessStats.writeToParcel(current, now, 0);
+ curTime = mProcessStats.mTimePeriodEndRealtime
+ - mProcessStats.mTimePeriodStartRealtime;
+ }
mWriteLock.lock();
try {
- Parcel current = Parcel.obtain();
- long curTime;
- synchronized (mAm) {
- long now = SystemClock.uptimeMillis();
- mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
- mProcessStats.mTimePeriodEndUptime = now;
- mProcessStats.writeToParcel(current, now, 0);
- curTime = mProcessStats.mTimePeriodEndRealtime
- - mProcessStats.mTimePeriodStartRealtime;
- }
if (curTime < minTime) {
// Need to add in older stats to reach desired time.
ArrayList<String> files = getCommittedFiles(0, false, true);
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 98f2997..95ed7bc 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -35,13 +35,22 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
/**
- * Centralized access to SELinux MMAC (middleware MAC) implementation.
+ * Centralized access to SELinux MMAC (middleware MAC) implementation. This
+ * class is responsible for loading the appropriate mac_permissions.xml file
+ * as well as providing an interface for assigning seinfo values to apks.
+ *
* {@hide}
*/
public final class SELinuxMMAC {
@@ -51,11 +60,9 @@
private static final boolean DEBUG_POLICY = false;
private static final boolean DEBUG_POLICY_INSTALL = DEBUG_POLICY || false;
- // Signature seinfo values read from policy.
- private static HashMap<Signature, Policy> sSigSeinfo = new HashMap<Signature, Policy>();
-
- // Default seinfo read from policy.
- private static String sDefaultSeinfo = null;
+ // All policy stanzas read from mac_permissions.xml. This is also the lock
+ // to synchronize access during policy load and access attempts.
+ private static final List<Policy> sPolicies = new ArrayList<Policy>();
// Data policy override version file.
private static final String DATA_VERSION_FILE =
@@ -94,293 +101,289 @@
private static final String SEAPP_HASH_FILE =
Environment.getDataDirectory().toString() + "/system/seapp_hash";
-
- // Signature policy stanzas
- static class Policy {
- private String seinfo;
- private final HashMap<String, String> pkgMap;
-
- Policy() {
- seinfo = null;
- pkgMap = new HashMap<String, String>();
- }
-
- void putSeinfo(String seinfoValue) {
- seinfo = seinfoValue;
- }
-
- void putPkg(String pkg, String seinfoValue) {
- pkgMap.put(pkg, seinfoValue);
- }
-
- // Valid policy stanza means there exists a global
- // seinfo value or at least one package policy.
- boolean isValid() {
- return (seinfo != null) || (!pkgMap.isEmpty());
- }
-
- String checkPolicy(String pkgName) {
- // Check for package name seinfo value first.
- String seinfoValue = pkgMap.get(pkgName);
- if (seinfoValue != null) {
- return seinfoValue;
- }
-
- // Return the global seinfo value.
- return seinfo;
- }
- }
-
- private static void flushInstallPolicy() {
- sSigSeinfo.clear();
- sDefaultSeinfo = null;
- }
-
+ /**
+ * Load the mac_permissions.xml file containing all seinfo assignments used to
+ * label apps. The loaded mac_permissions.xml file is determined by the
+ * MAC_PERMISSIONS class variable which is set at class load time which itself
+ * is based on the USE_OVERRIDE_POLICY class variable. For further guidance on
+ * the proper structure of a mac_permissions.xml file consult the source code
+ * located at external/sepolicy/mac_permissions.xml.
+ *
+ * @return boolean indicating if policy was correctly loaded. A value of false
+ * typically indicates a structural problem with the xml or incorrectly
+ * constructed policy stanzas. A value of true means that all stanzas
+ * were loaded successfully; no partial loading is possible.
+ */
public static boolean readInstallPolicy() {
- return readInstallPolicy(MAC_PERMISSIONS);
- }
+ // Temp structure to hold the rules while we parse the xml file. We add
+ // all the rules once we know there's no problems.
+ List<Policy> policies = new ArrayList<>();
- public static boolean readInstallPolicy(String macPermsPath) {
- if (macPermsPath == null) {
- throw new NullPointerException("mac_permissions.xml file path is null");
- }
+ // A separate structure to hold the default stanza. We need to add this to
+ // the end of the policies list structure.
+ Policy defaultPolicy = null;
- // Temp structures to hold the rules while we parse the xml file.
- // We add all the rules together once we know there's no structural problems.
- HashMap<Signature, Policy> sigSeinfo = new HashMap<Signature, Policy>();
- String defaultSeinfo = null;
+ // Track sets of known policy certs so we can enforce rules across stanzas.
+ Set<Set<Signature>> knownCerts = new HashSet<>();
FileReader policyFile = null;
+ XmlPullParser parser = Xml.newPullParser();
try {
- policyFile = new FileReader(macPermsPath);
- Slog.d(TAG, "Using policy file " + macPermsPath);
+ policyFile = new FileReader(MAC_PERMISSIONS);
+ Slog.d(TAG, "Using policy file " + MAC_PERMISSIONS);
- XmlPullParser parser = Xml.newPullParser();
parser.setInput(policyFile);
+ parser.nextTag();
+ parser.require(XmlPullParser.START_TAG, null, "policy");
- XmlUtils.beginDocument(parser, "policy");
- while (true) {
- XmlUtils.nextElement(parser);
- if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
- break;
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ continue;
}
String tagName = parser.getName();
if ("signer".equals(tagName)) {
- String cert = parser.getAttributeValue(null, "signature");
- if (cert == null) {
- Slog.w(TAG, "<signer> without signature at "
- + parser.getPositionDescription());
- XmlUtils.skipCurrentTag(parser);
- continue;
+ Policy signerPolicy = readSignerOrThrow(parser);
+ // Return of a Policy instance ensures certain invariants have
+ // passed, however, we still want to do some cross policy checking.
+ // Thus, check that we haven't seen the certs in another stanza.
+ Set<Signature> certs = signerPolicy.getSignatures();
+ if (knownCerts.contains(certs)) {
+ String msg = "Separate stanzas have identical certs";
+ throw new IllegalStateException(msg);
}
- Signature signature;
- try {
- signature = new Signature(cert);
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "<signer> with bad signature at "
- + parser.getPositionDescription(), e);
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
- Policy policy = readPolicyTags(parser);
- if (policy.isValid()) {
- sigSeinfo.put(signature, policy);
- }
+ knownCerts.add(certs);
+ policies.add(signerPolicy);
} else if ("default".equals(tagName)) {
- // Value is null if default tag is absent or seinfo tag is malformed.
- defaultSeinfo = readSeinfoTag(parser);
- if (DEBUG_POLICY_INSTALL)
- Slog.i(TAG, "<default> tag assigned seinfo=" + defaultSeinfo);
-
+ Policy defPolicy = readDefaultOrThrow(parser);
+ // Return of a Policy instance ensures certain invariants have
+ // passed, however, we still want to do some cross policy checking.
+ // Thus, check that we haven't already seen a default stanza.
+ if (defaultPolicy != null) {
+ String msg = "Multiple default stanzas identified";
+ throw new IllegalStateException(msg);
+ }
+ defaultPolicy = defPolicy;
} else {
- XmlUtils.skipCurrentTag(parser);
+ skip(parser);
}
}
- } catch (XmlPullParserException xpe) {
- Slog.w(TAG, "Got exception parsing " + macPermsPath, xpe);
+ } catch (IllegalStateException | IllegalArgumentException |
+ XmlPullParserException ex) {
+ StringBuilder sb = new StringBuilder("Exception @");
+ sb.append(parser.getPositionDescription());
+ sb.append(" while parsing ");
+ sb.append(MAC_PERMISSIONS);
+ sb.append(":");
+ sb.append(ex);
+ Slog.w(TAG, sb.toString());
return false;
} catch (IOException ioe) {
- Slog.w(TAG, "Got exception parsing " + macPermsPath, ioe);
+ Slog.w(TAG, "Exception parsing " + MAC_PERMISSIONS, ioe);
return false;
} finally {
IoUtils.closeQuietly(policyFile);
}
- flushInstallPolicy();
- sSigSeinfo = sigSeinfo;
- sDefaultSeinfo = defaultSeinfo;
+ // Add the default policy to the end if there is one. This will ensure that
+ // the default stanza is consulted last when performing policy lookups.
+ if (defaultPolicy != null) {
+ policies.add(defaultPolicy);
+ }
+
+ synchronized (sPolicies) {
+ sPolicies.clear();
+ sPolicies.addAll(policies);
+ }
return true;
}
- private static Policy readPolicyTags(XmlPullParser parser) throws
- IOException, XmlPullParserException {
+ /**
+ * Loop over a signer tag looking for seinfo, package and cert tags. A {@link Policy}
+ * instance will be created and returned in the process. During the pass all other
+ * tag elements will be skipped.
+ *
+ * @param parser an XmlPullParser object representing a signer element.
+ * @return the constructed {@link Policy} instance
+ * @throws IOException
+ * @throws XmlPullParserException
+ * @throws IllegalArgumentException if any of the validation checks fail while
+ * parsing tag values.
+ * @throws IllegalStateException if any of the invariants fail when constructing
+ * the {@link Policy} instance.
+ */
+ private static Policy readSignerOrThrow(XmlPullParser parser) throws IOException,
+ XmlPullParserException {
- int type;
- int outerDepth = parser.getDepth();
- Policy policy = new Policy();
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG
- || type == XmlPullParser.TEXT) {
+ parser.require(XmlPullParser.START_TAG, null, "signer");
+ Policy.PolicyBuilder pb = new Policy.PolicyBuilder();
+
+ // Check for a cert attached to the signer tag. We allow a signature
+ // to appear as an attribute as well as those attached to cert tags.
+ String cert = parser.getAttributeValue(null, "signature");
+ if (cert != null) {
+ pb.addSignature(cert);
+ }
+
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if ("seinfo".equals(tagName)) {
- String seinfo = parseSeinfo(parser);
- if (seinfo != null) {
- policy.putSeinfo(seinfo);
- }
- XmlUtils.skipCurrentTag(parser);
+ String seinfo = parser.getAttributeValue(null, "value");
+ pb.setGlobalSeinfoOrThrow(seinfo);
+ readSeinfo(parser);
} else if ("package".equals(tagName)) {
- String pkg = parser.getAttributeValue(null, "name");
- if (!validatePackageName(pkg)) {
- Slog.w(TAG, "<package> without valid name at "
- + parser.getPositionDescription());
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
-
- String seinfo = readSeinfoTag(parser);
- if (seinfo != null) {
- policy.putPkg(pkg, seinfo);
- }
+ readPackageOrThrow(parser, pb);
+ } else if ("cert".equals(tagName)) {
+ String sig = parser.getAttributeValue(null, "signature");
+ pb.addSignature(sig);
+ readCert(parser);
} else {
- XmlUtils.skipCurrentTag(parser);
+ skip(parser);
}
}
- return policy;
+
+ return pb.build();
}
- private static String readSeinfoTag(XmlPullParser parser) throws
- IOException, XmlPullParserException {
+ /**
+ * Loop over a default element looking for seinfo child tags. A {@link Policy}
+ * instance will be created and returned in the process. All other tags encountered
+ * will be skipped.
+ *
+ * @param parser an XmlPullParser object representing a default element.
+ * @return the constructed {@link Policy} instance
+ * @throws IOException
+ * @throws XmlPullParserException
+ * @throws IllegalArgumentException if any of the validation checks fail while
+ * parsing tag values.
+ * @throws IllegalStateException if any of the invariants fail when constructing
+ * the {@link Policy} instance.
+ */
+ private static Policy readDefaultOrThrow(XmlPullParser parser) throws IOException,
+ XmlPullParserException {
- int type;
- int outerDepth = parser.getDepth();
- String seinfo = null;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG
- || type == XmlPullParser.TEXT) {
+ parser.require(XmlPullParser.START_TAG, null, "default");
+ Policy.PolicyBuilder pb = new Policy.PolicyBuilder();
+ pb.setAsDefaultPolicy();
+
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if ("seinfo".equals(tagName)) {
- seinfo = parseSeinfo(parser);
+ String seinfo = parser.getAttributeValue(null, "value");
+ pb.setGlobalSeinfoOrThrow(seinfo);
+ readSeinfo(parser);
+ } else {
+ skip(parser);
}
- XmlUtils.skipCurrentTag(parser);
}
- return seinfo;
- }
- private static String parseSeinfo(XmlPullParser parser) {
-
- String seinfoValue = parser.getAttributeValue(null, "value");
- if (!validateValue(seinfoValue)) {
- Slog.w(TAG, "<seinfo> without valid value at "
- + parser.getPositionDescription());
- seinfoValue = null;
- }
- return seinfoValue;
+ return pb.build();
}
/**
- * General validation routine for package names.
- * Returns a boolean indicating if the passed string
- * is a valid android package name.
+ * Loop over a package element looking for seinfo child tags. If found return the
+ * value attribute of the seinfo tag, otherwise return null. All other tags encountered
+ * will be skipped.
+ *
+ * @param parser an XmlPullParser object representing a package element.
+ * @param pb a Policy.PolicyBuilder instance to build
+ * @throws IOException
+ * @throws XmlPullParserException
+ * @throws IllegalArgumentException if any of the validation checks fail while
+ * parsing tag values.
+ * @throws IllegalStateException if there is a duplicate seinfo tag for the current
+ * package tag.
*/
- private static boolean validatePackageName(String name) {
- if (name == null)
- return false;
+ private static void readPackageOrThrow(XmlPullParser parser, Policy.PolicyBuilder pb) throws
+ IOException, XmlPullParserException {
+ parser.require(XmlPullParser.START_TAG, null, "package");
+ String pkgName = parser.getAttributeValue(null, "name");
- final int N = name.length();
- boolean hasSep = false;
- boolean front = true;
- for (int i=0; i<N; i++) {
- final char c = name.charAt(i);
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
- front = false;
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
- if (!front) {
- if ((c >= '0' && c <= '9') || c == '_') {
- continue;
- }
+
+ String tagName = parser.getName();
+ if ("seinfo".equals(tagName)) {
+ String seinfo = parser.getAttributeValue(null, "value");
+ pb.addInnerPackageMapOrThrow(pkgName, seinfo);
+ readSeinfo(parser);
+ } else {
+ skip(parser);
}
- if (c == '.') {
- hasSep = true;
- front = true;
- continue;
- }
- return false;
}
- return hasSep;
+ }
+
+ private static void readCert(XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ parser.require(XmlPullParser.START_TAG, null, "cert");
+ parser.nextTag();
+ }
+
+ private static void readSeinfo(XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ parser.require(XmlPullParser.START_TAG, null, "seinfo");
+ parser.nextTag();
+ }
+
+ private static void skip(XmlPullParser p) throws IOException, XmlPullParserException {
+ if (p.getEventType() != XmlPullParser.START_TAG) {
+ throw new IllegalStateException();
+ }
+ int depth = 1;
+ while (depth != 0) {
+ switch (p.next()) {
+ case XmlPullParser.END_TAG:
+ depth--;
+ break;
+ case XmlPullParser.START_TAG:
+ depth++;
+ break;
+ }
+ }
}
/**
- * General validation routine for tag values.
- * Returns a boolean indicating if the passed string
- * contains only letters or underscores.
- */
- private static boolean validateValue(String name) {
- if (name == null)
- return false;
-
- final int N = name.length();
- if (N == 0)
- return false;
-
- for (int i = 0; i < N; i++) {
- final char c = name.charAt(i);
- if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c != '_')) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Labels a package based on an seinfo tag from install policy.
- * The label is attached to the ApplicationInfo instance of the package.
+ * Applies a security label to a package based on an seinfo tag taken from a matched
+ * policy. All signature based policy stanzas are consulted first and, if no match
+ * is found, the default policy stanza is then consulted. The security label is
+ * attached to the ApplicationInfo instance of the package in the event that a matching
+ * policy was found.
+ *
* @param pkg object representing the package to be labeled.
- * @return boolean which determines whether a non null seinfo label
- * was assigned to the package. A null value simply meaning that
- * no policy matched.
+ * @return boolean which determines whether a non null seinfo label was assigned
+ * to the package. A null value simply represents that no policy matched.
*/
public static boolean assignSeinfoValue(PackageParser.Package pkg) {
-
- // We just want one of the signatures to match.
- for (Signature s : pkg.mSignatures) {
- if (s == null)
- continue;
-
- Policy policy = sSigSeinfo.get(s);
- if (policy != null) {
- String seinfo = policy.checkPolicy(pkg.packageName);
+ synchronized (sPolicies) {
+ for (Policy policy : sPolicies) {
+ String seinfo = policy.getMatchedSeinfo(pkg);
if (seinfo != null) {
pkg.applicationInfo.seinfo = seinfo;
- if (DEBUG_POLICY_INSTALL)
- Slog.i(TAG, "package (" + pkg.packageName +
- ") labeled with seinfo=" + seinfo);
-
+ if (DEBUG_POLICY_INSTALL) {
+ Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
+ "seinfo=" + seinfo);
+ }
return true;
}
}
}
- // If we have a default seinfo value then great, otherwise
- // we set a null object and that is what we started with.
- pkg.applicationInfo.seinfo = sDefaultSeinfo;
- if (DEBUG_POLICY_INSTALL)
- Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo="
- + (sDefaultSeinfo == null ? "null" : sDefaultSeinfo));
-
- return (sDefaultSeinfo != null);
+ if (DEBUG_POLICY_INSTALL) {
+ Slog.i(TAG, "package (" + pkg.packageName + ") doesn't match any policy; " +
+ "seinfo will remain null");
+ }
+ return false;
}
/**
@@ -485,3 +488,312 @@
return false;
}
}
+
+/**
+ * Holds valid policy representations of individual stanzas from a mac_permissions.xml
+ * file. Each instance can further be used to assign seinfo values to apks using the
+ * {@link Policy#getMatchedSeinfo} method. To create an instance of this use the
+ * {@link PolicyBuilder} pattern class, where each instance is validated against a set
+ * of invariants before being built and returned. Each instance can be guaranteed to
+ * hold one valid policy stanza as outlined in the external/sepolicy/mac_permissions.xml
+ * file.
+ * </p>
+ * The following is an example of how to use {@link Policy.PolicyBuilder} to create a
+ * signer based Policy instance.
+ * </p>
+ * <pre>
+ * {@code
+ * Policy policy = new Policy.PolicyBuilder()
+ * .addSignature("308204a8...")
+ * .addSignature("483538c8...")
+ * .setGlobalSeinfoOrThrow("paltform")
+ * .addInnerPackageMapOrThrow("com.foo.", "bar")
+ * .addInnerPackageMapOrThrow("com.foo.other", "bar")
+ * .build();
+ * }
+ * </pre>
+ * <p>
+ * An example of how to use {@link Policy.PolicyBuilder} to create a default based Policy
+ * instance.
+ * </p>
+ * <pre>
+ * {@code
+ * Policy policy = new Policy.PolicyBuilder()
+ * .setAsDefaultPolicy()
+ * .setGlobalSeinfoOrThrow("defualt")
+ * .build();
+ * }
+ * </pre>
+ */
+final class Policy {
+
+ private final String mSeinfo;
+ private final boolean mDefaultStanza;
+ private final Set<Signature> mCerts;
+ private final Map<String, String> mPkgMap;
+
+ // Use the PolicyBuilder pattern to instantiate
+ private Policy(PolicyBuilder builder) {
+ mSeinfo = builder.mSeinfo;
+ mDefaultStanza = builder.mDefaultStanza;
+ mCerts = Collections.unmodifiableSet(builder.mCerts);
+ mPkgMap = Collections.unmodifiableMap(builder.mPkgMap);
+ }
+
+ /**
+ * Return all the certs stored with this policy stanza.
+ *
+ * @return A set of Signature objects representing all the certs stored
+ * with the policy.
+ */
+ public Set<Signature> getSignatures() {
+ return mCerts;
+ }
+
+ /**
+ * <p>
+ * Determine the seinfo value to assign to an apk. The appropriate seinfo value
+ * is determined using the following steps:
+ * </p>
+ * <ul>
+ * <li> If this Policy instance is defined as a default stanza:
+ * <ul><li>Return the global seinfo value</li></ul>
+ * </li>
+ * <li> If this Policy instance is defined as a signer stanza:
+ * <ul>
+ * <li> All certs used to sign the apk and all certs stored with this policy
+ * instance are tested for set equality. If this fails then null is returned.
+ * </li>
+ * <li> If all certs match then an appropriate inner package stanza is
+ * searched based on package name alone. If matched, the stored seinfo
+ * value for that mapping is returned.
+ * </li>
+ * <li> If all certs matched and no inner package stanza matches then return
+ * the global seinfo value. The returned value can be null in this case.
+ * </li>
+ * </ul>
+ * </li>
+ * </ul>
+ * <p>
+ * In all cases, a return value of null should be interpreted as the apk failing
+ * to match this Policy instance; i.e. failing this policy stanza.
+ * </p>
+ * @param pkg the apk to check given as a PackageParser.Package object
+ * @return A string representing the seinfo matched during policy lookup.
+ * A value of null can also be returned if no match occured.
+ */
+ public String getMatchedSeinfo(PackageParser.Package pkg) {
+ if (!mDefaultStanza) {
+ // Check for exact signature matches across all certs.
+ Signature[] certs = mCerts.toArray(new Signature[0]);
+ if (!Signature.areExactMatch(certs, pkg.mSignatures)) {
+ return null;
+ }
+
+ // Check for inner package name matches given that the
+ // signature checks already passed.
+ String seinfoValue = mPkgMap.get(pkg.packageName);
+ if (seinfoValue != null) {
+ return seinfoValue;
+ }
+ }
+
+ // Return the global seinfo value (even if it's null).
+ return mSeinfo;
+ }
+
+ /**
+ * A nested builder class to create {@link Policy} instances. A {@link Policy}
+ * class instance represents one valid policy stanza found in a mac_permissions.xml
+ * file. A valid policy stanza is defined to be either a signer or default stanza
+ * which obeys the rules outlined in external/sepolicy/mac_permissions.xml. The
+ * {@link #build} method ensures a set of invariants are upheld enforcing the correct
+ * stanza structure before returning a valid Policy object.
+ */
+ public static final class PolicyBuilder {
+
+ private String mSeinfo;
+ private boolean mDefaultStanza;
+ private final Set<Signature> mCerts;
+ private final Map<String, String> mPkgMap;
+
+ public PolicyBuilder() {
+ mCerts = new HashSet<Signature>(2);
+ mPkgMap = new HashMap<String, String>(2);
+ }
+
+ /**
+ * Sets this stanza as a defualt stanza. All policy stanzas are assumed to
+ * be signer stanzas unless this method is explicitly called. Default stanzas
+ * are treated differently with respect to allowable child tags, ordering and
+ * when and how policy decisions are enforced.
+ *
+ * @return The reference to this PolicyBuilder.
+ */
+ public PolicyBuilder setAsDefaultPolicy() {
+ mDefaultStanza = true;
+ return this;
+ }
+
+ /**
+ * Adds a signature to the set of certs used for validation checks. The purpose
+ * being that all contained certs will need to be matched against all certs
+ * contained with an apk.
+ *
+ * @param cert the signature to add given as a String.
+ * @return The reference to this PolicyBuilder.
+ * @throws IllegalArgumentException if the cert value fails validation;
+ * null or is an invalid hex-encoded ASCII string.
+ */
+ public PolicyBuilder addSignature(String cert) {
+ if (cert == null) {
+ String err = "Invalid signature value " + cert;
+ throw new IllegalArgumentException(err);
+ }
+
+ mCerts.add(new Signature(cert));
+ return this;
+ }
+
+ /**
+ * Set the global seinfo tag for this policy stanza. The global seinfo tag
+ * represents the seinfo element that is used in one of two ways depending on
+ * its context. When attached to a signer tag the global seinfo represents an
+ * assignment when there isn't a further inner package refinement in policy.
+ * When used with a default tag, it represents the only allowable assignment
+ * value.
+ *
+ * @param seinfo the seinfo value given as a String.
+ * @return The reference to this PolicyBuilder.
+ * @throws IllegalArgumentException if the seinfo value fails validation;
+ * null, zero length or contains non-valid characters [^a-zA-Z_\._0-9].
+ * @throws IllegalStateException if an seinfo value has already been found
+ */
+ public PolicyBuilder setGlobalSeinfoOrThrow(String seinfo) {
+ if (!validateValue(seinfo)) {
+ String err = "Invalid seinfo value " + seinfo;
+ throw new IllegalArgumentException(err);
+ }
+
+ if (mSeinfo != null && !mSeinfo.equals(seinfo)) {
+ String err = "Duplicate seinfo tag found";
+ throw new IllegalStateException(err);
+ }
+
+ mSeinfo = seinfo;
+ return this;
+ }
+
+ /**
+ * Create a package name to seinfo value mapping. Each mapping represents
+ * the seinfo value that will be assigned to the described package name.
+ * These localized mappings allow the global seinfo to be overriden. This
+ * mapping provides no value when used in conjunction with a default stanza;
+ * enforced through the {@link #build} method.
+ *
+ * @param pkgName the android package name given to the app
+ * @param seinfo the seinfo value that will be assigned to the passed pkgName
+ * @return The reference to this PolicyBuilder.
+ * @throws IllegalArgumentException if the seinfo value fails validation;
+ * null, zero length or contains non-valid characters [^a-zA-Z_\.0-9].
+ * Or, if the package name isn't a valid android package name.
+ * @throws IllegalStateException if trying to reset a package mapping with a
+ * different seinfo value.
+ */
+ public PolicyBuilder addInnerPackageMapOrThrow(String pkgName, String seinfo) {
+ if (!validateValue(pkgName)) {
+ String err = "Invalid package name " + pkgName;
+ throw new IllegalArgumentException(err);
+ }
+ if (!validateValue(seinfo)) {
+ String err = "Invalid seinfo value " + seinfo;
+ throw new IllegalArgumentException(err);
+ }
+
+ String pkgValue = mPkgMap.get(pkgName);
+ if (pkgValue != null && !pkgValue.equals(seinfo)) {
+ String err = "Conflicting seinfo value found";
+ throw new IllegalStateException(err);
+ }
+
+ mPkgMap.put(pkgName, seinfo);
+ return this;
+ }
+
+ /**
+ * General validation routine for the attribute strings of an element. Checks
+ * if the string is non-null, positive length and only contains [a-zA-Z_\.0-9].
+ *
+ * @param name the string to validate.
+ * @return boolean indicating if the string was valid.
+ */
+ private boolean validateValue(String name) {
+ if (name == null)
+ return false;
+
+ // Want to match on [0-9a-zA-Z_.]
+ if (!name.matches("\\A[\\.\\w]+\\z")) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * <p>
+ * Create a {@link Policy} instance based on the current configuration. This
+ * method checks for certain policy invariants used to enforce certain guarantees
+ * about the expected structure of a policy stanza.
+ * Those invariants are:
+ * </p>
+ * <ul>
+ * <li> If a default stanza
+ * <ul>
+ * <li> an attached global seinfo tag must be present </li>
+ * <li> no signatures and no package names can be present </li>
+ * </ul>
+ * </li>
+ * <li> If a signer stanza
+ * <ul>
+ * <li> at least one cert must be found </li>
+ * <li> either a global seinfo value is present OR at least one
+ * inner package mapping must be present. </li>
+ * </ul>
+ * </li>
+ * </ul>
+ *
+ * @return an instance of {@link Policy} with the options set from this builder
+ * @throws IllegalStateException if an invariant is violated.
+ */
+ public Policy build() {
+ Policy p = new Policy(this);
+
+ if (p.mDefaultStanza) {
+ if (p.mSeinfo == null) {
+ String err = "Missing global seinfo tag with default stanza.";
+ throw new IllegalStateException(err);
+ }
+ if (p.mCerts.size() != 0) {
+ String err = "Certs not allowed with default stanza.";
+ throw new IllegalStateException(err);
+ }
+ if (!p.mPkgMap.isEmpty()) {
+ String err = "Inner package mappings not allowed with default stanza.";
+ throw new IllegalStateException(err);
+ }
+ } else {
+ if (p.mCerts.size() == 0) {
+ String err = "Missing certs with signer tag. Expecting at least one.";
+ throw new IllegalStateException(err);
+ }
+ if ((p.mSeinfo == null) && (p.mPkgMap.isEmpty())) {
+ String err = "Missing seinfo OR package tags with signer tag. At " +
+ "least one must be present.";
+ throw new IllegalStateException(err);
+ }
+ }
+
+ return p;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 30589b1..c6c2666 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -241,6 +241,7 @@
mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
}
}
+ mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
}
void switchUserStacks(int newUserId) {
diff --git a/services/core/java/com/android/server/wm/StackTapPointerEventListener.java b/services/core/java/com/android/server/wm/StackTapPointerEventListener.java
index 80eb453..1a85993 100644
--- a/services/core/java/com/android/server/wm/StackTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/StackTapPointerEventListener.java
@@ -31,7 +31,7 @@
private float mDownX;
private float mDownY;
private int mPointerId;
- final private Region mTouchExcludeRegion;
+ final private Region mTouchExcludeRegion = new Region();
private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
@@ -39,7 +39,6 @@
DisplayContent displayContent) {
mService = service;
mDisplayContent = displayContent;
- mTouchExcludeRegion = displayContent.mTouchExcludeRegion;
DisplayInfo info = displayContent.getDisplayInfo();
mMotionSlop = (int)(info.logicalDensityDpi * TAP_MOTION_SLOP_INCHES);
}
@@ -72,13 +71,15 @@
if (mPointerId == motionEvent.getPointerId(index)) {
final int x = (int)motionEvent.getX(index);
final int y = (int)motionEvent.getY(index);
- if ((motionEvent.getEventTime() - motionEvent.getDownTime())
- < TAP_TIMEOUT_MSEC
- && Math.abs(x - mDownX) < mMotionSlop
- && Math.abs(y - mDownY) < mMotionSlop
- && !mTouchExcludeRegion.contains(x, y)) {
- mService.mH.obtainMessage(H.TAP_OUTSIDE_STACK, x, y,
- mDisplayContent).sendToTarget();
+ synchronized(this) {
+ if ((motionEvent.getEventTime() - motionEvent.getDownTime())
+ < TAP_TIMEOUT_MSEC
+ && Math.abs(x - mDownX) < mMotionSlop
+ && Math.abs(y - mDownY) < mMotionSlop
+ && !mTouchExcludeRegion.contains(x, y)) {
+ mService.mH.obtainMessage(H.TAP_OUTSIDE_STACK, x, y,
+ mDisplayContent).sendToTarget();
+ }
}
mPointerId = -1;
}
@@ -86,4 +87,10 @@
}
}
}
+
+ void setTouchExcludeRegion(Region newRegion) {
+ synchronized (this) {
+ mTouchExcludeRegion.set(newRegion);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 238c77e..802cf4b 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -191,7 +191,9 @@
mTasks.add(stackNdx, task);
task.mStack = this;
- mDisplayContent.moveStack(this, true);
+ if (toTop) {
+ mDisplayContent.moveStack(this, true);
+ }
EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, stackNdx);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1c03ced..c80d0e1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8796,7 +8796,8 @@
if (!gone || !win.mHaveFrame || win.mLayoutNeeded
|| ((win.isConfigChanged() || win.setInsetsChanged()) &&
((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
- win.mAppToken != null && win.mAppToken.layoutConfigChanges))
+ (win.mHasSurface && win.mAppToken != null &&
+ win.mAppToken.layoutConfigChanges)))
|| win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
if (!win.mLayoutAttached) {
if (initial) {
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index a58b00bce..3d981ab 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -290,7 +290,7 @@
epollfd = epoll_create(N_ANDROID_TIMERFDS);
if (epollfd < 0) {
- ALOGV("epoll_create(%u) failed: %s", N_ANDROID_TIMERFDS,
+ ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS,
strerror(errno));
return 0;
}
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index d730b7e..b18b14d 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -214,7 +214,7 @@
size_t status_size = agps_status->size;
if (status_size == sizeof(AGpsStatus_v3)) {
- ALOGV("AGpsStatus is V3: %d", status_size);
+ ALOGV("AGpsStatus is V3: %zd", status_size);
switch (agps_status->addr.ss_family)
{
case AF_INET:
@@ -256,7 +256,7 @@
break;
}
} else if (status_size >= sizeof(AGpsStatus_v2)) {
- ALOGV("AGpsStatus is V2+: %d", status_size);
+ ALOGV("AGpsStatus is V2+: %zd", status_size);
// for back-compatibility reasons we check in v2 that the data structure size is greater or
// equal to the declared size in gps.h
uint32_t ipaddr = agps_status->ipaddr;
@@ -266,12 +266,12 @@
isSupported = true;
}
} else if (status_size >= sizeof(AGpsStatus_v1)) {
- ALOGV("AGpsStatus is V1+: %d", status_size);
+ ALOGV("AGpsStatus is V1+: %zd", status_size);
// because we have to check for >= with regards to v2, we also need to relax the check here
// and only make sure that the size is at least what we expect
isSupported = true;
} else {
- ALOGE("Invalid size of AGpsStatus found: %d.", status_size);
+ ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
}
if (isSupported) {
@@ -758,7 +758,7 @@
} else if (interface_size == sizeof(AGpsInterface_v1)) {
sAGpsInterface->data_conn_open(apnStr);
} else {
- ALOGE("Invalid size of AGpsInterface found: %d.", interface_size);
+ ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
}
env->ReleaseStringUTFChars(apn, apnStr);
@@ -1260,7 +1260,7 @@
env->DeleteLocalRef(gpsMeasurementsEventClass);
env->DeleteLocalRef(gpsMeasurementsEvent);
} else {
- ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%d", data->size);
+ ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%zd", data->size);
}
}
@@ -1311,7 +1311,7 @@
size_t dataLength = message->data_length;
uint8_t* data = message->data;
if (dataLength == 0 || data == NULL) {
- ALOGE("Invalid Navigation Message found: data=%p, length=%d", data, dataLength);
+ ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
return NULL;
}
@@ -1370,7 +1370,7 @@
env->DeleteLocalRef(navigationMessageEventClass);
env->DeleteLocalRef(navigationMessageEvent);
} else {
- ALOGE("Invalid GpsNavigationMessage size found: %d", message->size);
+ ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
}
}
diff --git a/tests/CoreTests/android/core/InetAddrTest.java b/tests/CoreTests/android/core/InetAddrTest.java
deleted file mode 100644
index c7b89e1..0000000
--- a/tests/CoreTests/android/core/InetAddrTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import junit.framework.TestCase;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Random;
-
-import android.test.suitebuilder.annotation.Suppress;
-
-/**
- * Tests InetAddr class by checking methods to resolve domains to IP addresses
- * and by checking if the class returns correct addresses for local host address
- * and host name.
- */
-@Suppress
-public class InetAddrTest extends TestCase {
- private static final String[] HOSTS = {
- "localhost", "www.google.com", "www.slashdot.org", "www.wikipedia.org",
- "www.paypal.com", "www.cnn.com", "www.yahoo.com", "www.amazon.com",
- "www.ebay.com", "www.android.com"
- };
-
- public void testInetAddr() throws Exception {
- byte[] raw;
-
- InetAddress ia = InetAddress.getByName("localhost");
-
- raw = ia.getAddress();
-
- assertEquals(127, raw[0]);
- assertEquals(0, raw[1]);
- assertEquals(0, raw[2]);
- assertEquals(1, raw[3]);
-
- ia = InetAddress.getByName("127.0.0.1");
-
- raw = ia.getAddress();
-
- assertEquals(127, raw[0]);
- assertEquals(0, raw[1]);
- assertEquals(0, raw[2]);
- assertEquals(1, raw[3]);
-
- ia = InetAddress.getByName(null);
-
- try {
- InetAddress.getByName(".0.0.1");
- fail("expected ex");
- } catch (UnknownHostException ex) {
- // expected
- }
-
- try {
- InetAddress.getByName("thereisagoodchancethisdomaindoesnotexist.weirdtld");
- fail("expected ex");
- } catch (UnknownHostException ex) {
- // expected
- }
-
- try {
- InetAddress.getByName("127.0.0.");
- fail("expected ex");
- } catch (UnknownHostException ex) {
- // expected
- }
-
- Random random = new Random();
- int count = 0;
- for (int i = 0; i < 100; i++) {
- int index = random.nextInt(HOSTS.length);
- try {
- InetAddress.getByName(HOSTS[index]);
- count++;
- try {
- Thread.sleep(50);
- } catch (InterruptedException ex) {
- }
- } catch (UnknownHostException ex) {
- }
- }
- assertEquals("Not all host lookups succeeded", 100, count);
- }
-}
diff --git a/tests/CoreTests/android/core/SSLSocketTest.java b/tests/CoreTests/android/core/SSLSocketTest.java
deleted file mode 100644
index 65062c2..0000000
--- a/tests/CoreTests/android/core/SSLSocketTest.java
+++ /dev/null
@@ -1,1094 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import junit.framework.TestCase;
-
-import com.android.org.conscrypt.FileClientSessionCache;
-import com.android.org.conscrypt.OpenSSLContextImpl;
-import com.android.org.conscrypt.SSLClientSessionCache;
-import org.apache.commons.codec.binary.Base64;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.security.KeyStore;
-import java.security.KeyManagementException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * SSL integration tests that hit real servers.
- */
-public class SSLSocketTest extends TestCase {
-
- private static SSLSocketFactory clientFactory =
- (SSLSocketFactory) SSLSocketFactory.getDefault();
-
- /**
- * Does a number of HTTPS requests on some host and consumes the response.
- * We don't use the HttpsUrlConnection class, but do this on our own
- * with the SSLSocket class. This gives us a chance to test the basic
- * behavior of SSL.
- *
- * @param host The host name the request is being sent to.
- * @param port The port the request is being sent to.
- * @param path The path being requested (e.g. "/index.html").
- * @param outerLoop The number of times we reconnect and do the request.
- * @param innerLoop The number of times we do the request for each
- * connection (using HTTP keep-alive).
- * @param delay The delay after each request (in seconds).
- * @throws IOException When a problem occurs.
- */
- private void fetch(SSLSocketFactory socketFactory, String host, int port,
- boolean secure, String path, int outerLoop, int innerLoop,
- int delay, int timeout) throws IOException {
- InetSocketAddress address = new InetSocketAddress(host, port);
-
- for (int i = 0; i < outerLoop; i++) {
- // Connect to the remote host
- Socket socket = secure ? socketFactory.createSocket()
- : new Socket();
- if (timeout >= 0) {
- socket.setKeepAlive(true);
- socket.setSoTimeout(timeout * 1000);
- }
- socket.connect(address);
-
- // Get the streams
- OutputStream output = socket.getOutputStream();
- PrintWriter writer = new PrintWriter(output);
-
- try {
- DataInputStream input = new DataInputStream(socket.getInputStream());
- try {
- for (int j = 0; j < innerLoop; j++) {
- android.util.Log.d("SSLSocketTest",
- "GET https://" + host + path + " HTTP/1.1");
-
- // Send a request
- writer.println("GET https://" + host + path + " HTTP/1.1\r");
- writer.println("Host: " + host + "\r");
- writer.println("Connection: " +
- (j == innerLoop - 1 ? "Close" : "Keep-Alive")
- + "\r");
- writer.println("\r");
- writer.flush();
-
- int length = -1;
- boolean chunked = false;
-
- String line = input.readLine();
-
- if (line == null) {
- throw new IOException("No response from server");
- // android.util.Log.d("SSLSocketTest", "No response from server");
- }
-
- // Consume the headers, check content length and encoding type
- while (line != null && line.length() != 0) {
-// System.out.println(line);
- int dot = line.indexOf(':');
- if (dot != -1) {
- String key = line.substring(0, dot).trim();
- String value = line.substring(dot + 1).trim();
-
- if ("Content-Length".equalsIgnoreCase(key)) {
- length = Integer.valueOf(value);
- } else if ("Transfer-Encoding".equalsIgnoreCase(key)) {
- chunked = "Chunked".equalsIgnoreCase(value);
- }
-
- }
- line = input.readLine();
- }
-
- assertTrue("Need either content length or chunked encoding", length != -1
- || chunked);
-
- // Consume the content itself
- if (chunked) {
- length = Integer.parseInt(input.readLine(), 16);
- while (length != 0) {
- byte[] buffer = new byte[length];
- input.readFully(buffer);
- input.readLine();
- length = Integer.parseInt(input.readLine(), 16);
- }
- input.readLine();
- } else {
- byte[] buffer = new byte[length];
- input.readFully(buffer);
- }
-
- // Sleep for the given number of seconds
- try {
- Thread.sleep(delay * 1000);
- } catch (InterruptedException ex) {
- // Shut up!
- }
- }
- } finally {
- input.close();
- }
- } finally {
- writer.close();
- }
- // Close the connection
- socket.close();
- }
- }
-
- /**
- * Invokes fetch() with the default socket factory.
- */
- private void fetch(String host, int port, boolean secure, String path,
- int outerLoop, int innerLoop,
- int delay, int timeout) throws IOException {
- fetch(clientFactory, host, port, secure, path, outerLoop, innerLoop,
- delay, timeout);
- }
-
- /**
- * Does a single request for each of the hosts. Consumes the response.
- *
- * @throws IOException If a problem occurs.
- */
- public void testSimple() throws IOException {
- fetch("www.fortify.net", 443, true, "/sslcheck.html", 1, 1, 0, 60);
- fetch("mail.google.com", 443, true, "/mail/", 1, 1, 0, 60);
- fetch("www.paypal.com", 443, true, "/", 1, 1, 0, 60);
- fetch("www.yellownet.ch", 443, true, "/", 1, 1, 0, 60);
- }
-
- /**
- * Does repeated requests for each of the hosts, with the connection being
- * closed in between.
- *
- * @throws IOException If a problem occurs.
- */
- public void testRepeatedClose() throws IOException {
- fetch("www.fortify.net", 443, true, "/sslcheck.html", 10, 1, 0, 60);
- fetch("mail.google.com", 443, true, "/mail/", 10, 1, 0, 60);
- fetch("www.paypal.com", 443, true, "/", 10, 1, 0, 60);
- fetch("www.yellownet.ch", 443, true, "/", 10, 1, 0, 60);
- }
-
- /**
- * Does repeated requests for each of the hosts, with the connection being
- * kept alive in between.
- *
- * @throws IOException If a problem occurs.
- */
- public void testRepeatedKeepAlive() throws IOException {
- fetch("www.fortify.net", 443, true, "/sslcheck.html", 1, 10, 0, 60);
- fetch("mail.google.com", 443, true, "/mail/", 1, 10, 0, 60);
-
- // These two don't accept keep-alive
- // fetch("www.paypal.com", 443, "/", 1, 10);
- // fetch("www.yellownet.ch", 443, "/", 1, 10);
- }
-
- /**
- * Does repeated requests for each of the hosts, with the connection being
- * closed in between. Waits a couple of seconds after each request, but
- * stays within a reasonable timeout. Expectation is that the connection
- * stays open.
- *
- * @throws IOException If a problem occurs.
- */
- public void testShortTimeout() throws IOException {
- fetch("www.fortify.net", 443, true, "/sslcheck.html", 1, 10, 5, 60);
- fetch("mail.google.com", 443, true, "/mail/", 1, 10, 5, 60);
-
- // These two don't accept keep-alive
- // fetch("www.paypal.com", 443, "/", 1, 10);
- // fetch("www.yellownet.ch", 443, "/", 1, 10);
- }
-
- /**
- * Does repeated requests for each of the hosts, with the connection being
- * kept alive in between. Waits a longer time after each request.
- * Expectation is that the host closes the connection.
- */
- public void testLongTimeout() {
- // Seems to have a veeeery long timeout.
- // fetch("www.fortify.net", 443, "/sslcheck.html", 1, 2, 60);
-
- // Google has a 60s timeout, so 90s of waiting should trigger it.
- try {
- fetch("mail.google.com", 443, true, "/mail/", 1, 2, 90, 180);
- fail("Oops - timeout expected.");
- } catch (IOException ex) {
- // Expected.
- }
-
- // These two don't accept keep-alive
- // fetch("www.paypal.com", 443, "/", 1, 10);
- // fetch("www.yellownet.ch", 443, "/", 1, 10);
- }
-
- /**
- * Does repeated requests for each of the hosts, with the connection being
- * closed in between. Waits a longer time after each request. Expectation is
- * that the host closes the connection.
- */
- // These two need manual interaction to reproduce...
- public void xxtestBrokenConnection() {
- try {
- fetch("www.fortify.net", 443, true, "/sslcheck.html", 1, 2, 60, 60);
- fail("Oops - timeout expected.");
- } catch (IOException ex) {
- android.util.Log.d("SSLSocketTest", "Exception", ex);
- // Expected.
- }
-
- // These two don't accept keep-alive
- // fetch("www.paypal.com", 443, "/", 1, 10);
- // fetch("www.yellownet.ch", 443, "/", 1, 10);
- }
-
- /**
- * Does repeated requests for each of the hosts, with the connection being
- * closed in between. Waits a longer time after each request. Expectation is
- * that the host closes the connection.
- */
- // These two need manual interaction to reproduce...
- public void xxtestBrokenConnection2() {
- try {
- fetch("www.heise.de", 80, false, "/index.html", 1, 2, 60, 60);
- fail("Oops - timeout expected.");
- } catch (IOException ex) {
- android.util.Log.d("SSLSocketTest", "Exception", ex);
- // Expected.
- }
-
- // These two don't accept keep-alive
- // fetch("www.paypal.com", 443, "/", 1, 10);
- // fetch("www.yellownet.ch", 443, "/", 1, 10);
- }
-
- /**
- * Regression test for 865926: SSLContext.init() should
- * use default values for null arguments.
- */
- public void testContextInitNullArgs() throws Exception {
- SSLContext ctx = SSLContext.getInstance("TLS");
- ctx.init(null, null, null);
- }
-
- /**
- * Regression test for 963650: javax.net.ssl.KeyManager has no implemented
- * (documented?) algorithms.
- */
- public void testDefaultAlgorithms() throws Exception {
- SSLContext ctx = SSLContext.getInstance("TLS");
- KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
- KeyStore ks = KeyStore.getInstance("BKS");
-
- assertEquals("X509", kmf.getAlgorithm());
- assertEquals("X509", KeyManagerFactory.getDefaultAlgorithm());
-
- assertEquals("BKS", ks.getType());
- assertEquals("BKS", KeyStore.getDefaultType());
- }
-
- /**
- * Regression test for problem where close() resulted in a hand if
- * a different thread was sitting in a blocking read or write.
- */
- public void testMultithreadedClose() throws Exception {
- InetSocketAddress address = new InetSocketAddress("www.fortify.net", 443);
- final Socket socket = clientFactory.createSocket();
- socket.connect(address);
-
- Thread reader = new Thread() {
- @Override
- public void run() {
- try {
- byte[] buffer = new byte[512];
- InputStream stream = socket.getInputStream();
- socket.getInputStream().read(buffer);
- } catch (Exception ex) {
- android.util.Log.d("SSLSocketTest",
- "testMultithreadedClose() reader got " + ex.toString());
- }
- }
- };
-
- Thread closer = new Thread() {
- @Override
- public void run() {
- try {
- Thread.sleep(5000);
- socket.close();
- } catch (Exception ex) {
- android.util.Log.d("SSLSocketTest",
- "testMultithreadedClose() closer got " + ex.toString());
- }
- }
- };
-
- android.util.Log.d("SSLSocketTest", "testMultithreadedClose() starting reader...");
- reader.start();
- android.util.Log.d("SSLSocketTest", "testMultithreadedClose() starting closer...");
- closer.start();
-
- long t1 = System.currentTimeMillis();
- android.util.Log.d("SSLSocketTest", "testMultithreadedClose() joining reader...");
- reader.join(30000);
- android.util.Log.d("SSLSocketTest", "testMultithreadedClose() joining closer...");
- closer.join(30000);
- long t2 = System.currentTimeMillis();
-
- assertTrue("Concurrent close() hangs", t2 - t1 < 30000);
- }
-
- private int multithreadedFetchRuns;
-
- private int multithreadedFetchWins;
-
- private Random multithreadedFetchRandom = new Random();
-
- /**
- * Regression test for problem where multiple threads with multiple SSL
- * connection would cause problems due to either missing native locking
- * or the slowness of the SSL connections.
- */
- public void testMultithreadedFetch() {
- Thread[] threads = new Thread[10];
-
- for (int i = 0; i < threads.length; i++) {
- threads[i] = new Thread() {
- @Override
- public void run() {
- for (int i = 0; i < 10; i++) {
- try {
- multithreadedFetchRuns++;
- switch (multithreadedFetchRandom.nextInt(4)) {
- case 0: {
- fetch("www.fortify.net", 443,
- true, "/sslcheck.html", 1, 1, 0, 60);
- break;
- }
-
- case 1: {
- fetch("mail.google.com", 443, true, "/mail/", 1, 1, 0, 60);
- break;
- }
-
- case 2: {
- fetch("www.paypal.com", 443, true, "/", 1, 1, 0, 60);
- break;
- }
-
- case 3: {
- fetch("www.yellownet.ch", 443, true, "/", 1, 1, 0, 60);
- break;
- }
- }
- multithreadedFetchWins++;
- } catch (Exception ex) {
- android.util.Log.d("SSLSocketTest",
- "testMultithreadedFetch() got Exception", ex);
- }
- }
- }
- };
- threads[i].start();
-
- android.util.Log.d("SSLSocketTest", "testMultithreadedFetch() started thread #" + i);
- }
-
- for (int i = 0; i < threads.length; i++) {
- try {
- threads[i].join();
- android.util.Log.d("SSLSocketTest", "testMultithreadedFetch() joined thread #" + i);
- } catch (InterruptedException ex) {
- // Not interested.
- }
- }
-
- assertTrue("At least 95% of multithreaded SSL connections must succeed",
- multithreadedFetchWins >= (multithreadedFetchRuns * 95) / 100);
- }
-
- // -------------------------------------------------------------------------
- // Regression test for #1204316: Missing client cert unit test. Passes on
- // both Android and the RI. To use on the RI, install Apache Commons and
- // replace the references to the base64-encoded keys by the JKS versions.
- // -------------------------------------------------------------------------
-
- /**
- * Defines the keystore contents for the server, JKS version. Holds just a
- * single self-generated key. The subject name is "Test Server".
- */
- private static final String SERVER_KEYS_JKS =
- "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFfBeAAAArowggK2MA4GCisGAQQBKgIRAQEFAASC" +
- "AqI2kp5XjnF8YZkhcF92YsJNQkvsmH7zqMM87j23zSoV4DwyE3XeC/gZWq1ToScIhoqZkzlbWcu4" +
- "T/Zfc/DrfGk/rKbBL1uWKGZ8fMtlZk8KoAhxZk1JSyJvdkyKxqmzUbxk1OFMlN2VJNu97FPVH+du" +
- "dvjTvmpdoM81INWBW/1fZJeQeDvn4mMbbe0IxgpiLnI9WSevlaDP/sm1X3iO9yEyzHLL+M5Erspo" +
- "Cwa558fOu5DdsICMXhvDQxjWFKFhPHnKtGe+VvwkG9/bAaDgx3kfhk0w5zvdnkKb+8Ed9ylNRzdk" +
- "ocAa/mxlMTOsTvDKXjjsBupNPIIj7OP4GNnZaxkJjSs98pEO67op1GX2qhy6FSOPNuq8k/65HzUc" +
- "PYn6voEeh6vm02U/sjEnzRevQ2+2wXoAdp0EwtQ/DlMe+NvcwPGWKuMgX4A4L93DZGb04N2VmAU3" +
- "YLOtZwTO0LbuWrcCM/q99G/7LcczkxIVrO2I/rh8RXVczlf9QzcrFObFv4ATuspWJ8xG7DhsMbnk" +
- "rT94Pq6TogYeoz8o8ZMykesAqN6mt/9+ToIemmXv+e+KU1hI5oLwWMnUG6dXM6hIvrULY6o+QCPH" +
- "172YQJMa+68HAeS+itBTAF4Clm/bLn6reHCGGU6vNdwU0lYldpiOj9cB3t+u2UuLo6tiFWjLf5Zs" +
- "EQJETd4g/EK9nHxJn0GAKrWnTw7pEHQJ08elzUuy04C/jEEG+4QXU1InzS4o/kR0Sqz2WTGDoSoq" +
- "ewuPRU5bzQs/b9daq3mXrnPtRBL6HfSDAdpTK76iHqLCGdqx3avHjVSBm4zFvEuYBCev+3iKOBmg" +
- "yh7eQRTjz4UOWfy85omMBr7lK8PtfVBDzOXpasxS0uBgdUyBDX4tO6k9jZ8a1kmQRQAAAAEABVgu" +
- "NTA5AAACSDCCAkQwggGtAgRIR8SKMA0GCSqGSIb3DQEBBAUAMGkxCzAJBgNVBAYTAlVTMRMwEQYD" +
- "VQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMH" +
- "QW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBTZXJ2ZXIwHhcNMDgwNjA1MTA0ODQyWhcNMDgwOTAzMTA0" +
- "ODQyWjBpMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8w" +
- "DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMIGf" +
- "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwoC6chqCI84rj1PrXuJgbiit4EV909zR6N0jNlYfg" +
- "itwB39bP39wH03rFm8T59b3mbSptnGmCIpLZn25KPPFsYD3JJ+wFlmiUdEP9H05flfwtFQJnw9uT" +
- "3rRIdYVMPcQ3RoZzwAMliGr882I2thIDbA6xjGU/1nRIdvk0LtxH3QIDAQABMA0GCSqGSIb3DQEB" +
- "BAUAA4GBAJn+6YgUlY18Ie+0+Vt8oEi81DNi/bfPrAUAh63fhhBikx/3R9dl3wh09Z6p7cIdNxjW" +
- "n2ll+cRW9eqF7z75F0Omm0C7/KAEPjukVbszmzeU5VqzkpSt0j84YWi+TfcHRrfvhLbrlmGITVpY" +
- "ol5pHLDyqGmDs53pgwipWqsn/nEXEBgj3EoqPeqHbDf7YaP8h/5BSt0=";
-
- /**
- * Defines the keystore contents for the server, BKS version. Holds just a
- * single self-generated key. The subject name is "Test Server".
- */
- private static final String SERVER_KEYS_BKS =
- "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41" +
- "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
- "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
- "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw" +
- "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
- "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl" +
- "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy" +
- "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV" +
- "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG" +
- "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU" +
- "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV" +
- "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx" +
- "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR" +
- "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN" +
- "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs" +
- "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck" +
- "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM" +
- "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI" +
- "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f" +
- "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx" +
- "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt" +
- "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw" +
- "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" +
- "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
-
- /**
- * Defines the keystore contents for the client, JKS version. Holds just a
- * single self-generated key. The subject name is "Test Client".
- */
- private static final String CLIENT_KEYS_JKS =
- "/u3+7QAAAAIAAAABAAAAAQAFbXlrZXkAAAEaWFhyMAAAArkwggK1MA4GCisGAQQBKgIRAQEFAASC" +
- "AqGVSfXolBStZy4nnRNn4fAr+S7kfU2BS23wwW8uB2Ru3GvtLzlK9q08Gvq/LNqBafjyFTVL5FV5" +
- "SED/8YomO5a98GpskSeRvytCiTBLJdgGhws5TOGekgIAcBROPGIyOtJPQ0HfOQs+BqgzGDHzHQhw" +
- "u/8Tm6yQwiP+W/1I9B1QnaEztZA3mhTyMMJsmsFTYroGgAog885D5Cmzd8sYGfxec3R6I+xcmBAY" +
- "eibR5kGpWwt1R+qMvRrtBqh5r6WSKhCBNax+SJVbtUNRiKyjKccdJg6fGqIWWeivwYTy0OhjA6b4" +
- "NiZ/ZZs5pxFGWUj/Rlp0RYy8fCF6aw5/5s4Bf4MI6dPSqMG8Hf7sJR91GbcELyzPdM0h5lNavgit" +
- "QPEzKeuDrGxhY1frJThBsNsS0gxeu+OgfJPEb/H4lpYX5IvuIGbWKcxoO9zq4/fimIZkdA8A+3eY" +
- "mfDaowvy65NBVQPJSxaOyFhLHfeLqOeCsVENAea02vA7andZHTZehvcrqyKtm+z8ncHGRC2H9H8O" +
- "jKwKHfxxrYY/jMAKLl00+PBb3kspO+BHI2EcQnQuMw/zr83OR9Meq4TJ0TMuNkApZELAeFckIBbS" +
- "rBr8NNjAIfjuCTuKHhsTFWiHfk9ZIzigxXagfeDRiyVc6khOuF/bGorj23N2o7Rf3uLoU6PyXWi4" +
- "uhctR1aL6NzxDoK2PbYCeA9hxbDv8emaVPIzlVwpPK3Ruvv9mkjcOhZ74J8bPK2fQmbplbOljcZi" +
- "tZijOfzcO/11JrwhuJZRA6wanTqHoujgChV9EukVrmbWGGAcewFnAsSbFXIik7/+QznXaDIt5NgL" +
- "H/Bcz4Z/fdV7Ae1eUaxKXdPbI//4J+8liVT/d8awjW2tldIaDlmGMR3aoc830+3mAAAAAQAFWC41" +
- "MDkAAAJIMIICRDCCAa0CBEhHxLgwDQYJKoZIhvcNAQEEBQAwaTELMAkGA1UEBhMCVVMxEzARBgNV" +
- "BAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01UVjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdB" +
- "bmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVudDAeFw0wODA2MDUxMDQ5MjhaFw0wODA5MDMxMDQ5" +
- "MjhaMGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMQwwCgYDVQQHEwNNVFYxDzAN" +
- "BgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEUMBIGA1UEAxMLVGVzdCBDbGllbnQwgZ8w" +
- "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIK3Q+KiFbmCGg422TAo4gggdhMH6FJhiuz8DxRyeMKR" +
- "UAfP4MK0wtc8N42waZ6OKvxpBFUy0BRfBsX0GD4Ku99yu9/tavSigTraeJtwV3WWRRjIqk7L3wX5" +
- "cmgS2KSD43Y0rNUKrko26lnt9N4qiYRBSj+tcAN3Lx9+ptqk1LApAgMBAAEwDQYJKoZIhvcNAQEE" +
- "BQADgYEANb7Q1GVSuy1RPJ0FmiXoMYCCtvlRLkmJphwxovK0cAQK12Vll+yAzBhHiQHy/RA11mng" +
- "wYudC7u3P8X/tBT8GR1Yk7QW3KgFyPafp3lQBBCraSsfrjKj+dCLig1uBLUr4f68W8VFWZWWTHqp" +
- "NMGpCX6qmjbkJQLVK/Yfo1ePaUexPSOX0G9m8+DoV3iyNw6at01NRw==";
-
- /**
- * Defines the keystore contents for the client, BKS version. Holds just a
- * single self-generated key. The subject name is "Test Client".
- */
- private static final String CLIENT_KEYS_BKS =
- "AAAAAQAAABT4Rka6fxbFps98Y5k2VilmbibNkQAABfQEAAVteWtleQAAARpYl+POAAAAAQAFWC41" +
- "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU9TANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
- "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
- "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgQ2xpZW50MB4XDTA4MDYwNTExNTg0NVoXDTA4MDkw" +
- "MzExNTg0NVowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
- "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IENsaWVu" +
- "dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApUvmWsQDHPpbDKK13Yez2/q54tTOmRml/qva" +
- "2K6dZjkjSTW0iRuk7ztaVEvdJpfVIDv1oBsCI51ttyLHROy1epjF+GoL74mJb7fkcd0VOoSOTjtD" +
- "+3GgZkHPAm5YmUYxiJXqxKKJJqMCTIW46eJaA2nAep9QIwZ14/NFAs4ObV8CAwEAATANBgkqhkiG" +
- "9w0BAQUFAAOBgQCJrCr3hZQFDlLIfsSKI1/w+BLvyf4fubOid0pBxfklR8KBNPTiqjSmu7pd/C/F" +
- "1FR8CdZUDoPflZHCOU+fj5r5KUC1HyigY/tEUvlforBpfB0uCF+tXW4DbUfOWhfMtLV4nCOJOOZg" +
- "awfZLJWBJouLKOp427vDftxTSB+Ks8YjlgAAAqwAAAAU+NH6TtrzjyDdCXm5B6Vo7xX5G4YAAAZx" +
- "EAUkcZtmykn7YdaYxC1jRFJ+GEJpC8nZVg83QClVuCSIS8a5f8Hl44Bk4oepOZsPzhtz3RdVzDVi" +
- "RFfoyZFsrk9F5bDTVJ6sQbb/1nfJkLhZFXokka0vND5AXMSoD5Bj1Fqem3cK7fSUyqKvFoRKC3XD" +
- "FQvhqoam29F1rbl8FaYdPvhhZo8TfZQYUyUKwW+RbR44M5iHPx+ykieMe/C/4bcM3z8cwIbYI1aO" +
- "gjQKS2MK9bs17xaDzeAh4sBKrskFGrDe+2dgvrSKdoakJhLTNTBSG6m+rzqMSCeQpafLKMSjTSSz" +
- "+KoQ9bLyax8cbvViGGju0SlVhquloZmKOfHr8TukIoV64h3uCGFOVFtQjCYDOq6NbfRvMh14UVF5" +
- "zgDIGczoD9dMoULWxBmniGSntoNgZM+QP6Id7DBasZGKfrHIAw3lHBqcvB5smemSu7F4itRoa3D8" +
- "N7hhUEKAc+xA+8NKmXfiCBoHfPHTwDvt4IR7gWjeP3Xv5vitcKQ/MAfO5RwfzkYCXQ3FfjfzmsE1" +
- "1IfLRDiBj+lhQSulhRVStKI88Che3M4JUNGKllrc0nt1pWa1vgzmUhhC4LSdm6trTHgyJnB6OcS9" +
- "t2furYjK88j1AuB4921oxMxRm8c4Crq8Pyuf+n3YKi8Pl2BzBtw++0gj0ODlgwut8SrVj66/nvIB" +
- "jN3kLVahR8nZrEFF6vTTmyXi761pzq9yOVqI57wJGx8o3Ygox1p+pWUPl1hQR7rrhUbgK/Q5wno9" +
- "uJk07h3IZnNxE+/IKgeMTP/H4+jmyT4mhsexJ2BFHeiKF1KT/FMcJdSi+ZK5yoNVcYuY8aZbx0Ef" +
- "lHorCXAmLFB0W6Cz4KPP01nD9YBB4olxiK1t7m0AU9zscdivNiuUaB5OIEr+JuZ6dNw=";
- /**
- * Defines the password for the keystore.
- */
- private static final String PASSWORD = "android";
-
- /**
- * Implements basically a dummy TrustManager. It stores the certificate
- * chain it sees, so it can later be queried.
- */
- class TestTrustManager implements X509TrustManager {
-
- private X509Certificate[] chain;
-
- private String authType;
-
- public void checkClientTrusted(X509Certificate[] chain, String authType) {
- this.chain = chain;
- this.authType = authType;
- }
-
- public void checkServerTrusted(X509Certificate[] chain, String authType) {
- this.chain = chain;
- this.authType = authType;
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
-
- public X509Certificate[] getChain() {
- return chain;
- }
-
- public String getAuthType() {
- return authType;
- }
-
- }
-
- /**
- * Implements a test SSL socket server. It wait for a connection on a given
- * port, requests client authentication (if specified), and read 256 bytes
- * from the socket.
- */
- class TestServer implements Runnable {
-
- public static final int CLIENT_AUTH_NONE = 0;
-
- public static final int CLIENT_AUTH_WANTED = 1;
-
- public static final int CLIENT_AUTH_NEEDED = 2;
-
- private TestTrustManager trustManager;
-
- private Exception exception;
-
- private int port;
-
- private int clientAuth;
-
- private boolean provideKeys;
-
- public TestServer(int port, boolean provideKeys, int clientAuth) {
- this.port = port;
- this.clientAuth = clientAuth;
- this.provideKeys = provideKeys;
-
- trustManager = new TestTrustManager();
- }
-
- public void run() {
- try {
- KeyManager[] keyManagers = provideKeys
- ? getKeyManagers(SERVER_KEYS_BKS) : null;
- TrustManager[] trustManagers = new TrustManager[] {
- trustManager };
-
- SSLContext sslContext = SSLContext.getInstance("TLS");
- sslContext.init(keyManagers, trustManagers, null);
-
- SSLServerSocket serverSocket
- = (SSLServerSocket) sslContext.getServerSocketFactory()
- .createServerSocket();
-
- if (clientAuth == CLIENT_AUTH_WANTED) {
- serverSocket.setWantClientAuth(true);
- } else if (clientAuth == CLIENT_AUTH_NEEDED) {
- serverSocket.setNeedClientAuth(true);
- } else {
- serverSocket.setWantClientAuth(false);
- }
-
- serverSocket.bind(new InetSocketAddress(port));
-
- SSLSocket clientSocket = (SSLSocket) serverSocket.accept();
-
- InputStream stream = clientSocket.getInputStream();
-
- for (int i = 0; i < 256; i++) {
- int j = stream.read();
- if (i != j) {
- throw new RuntimeException("Error reading socket,"
- + " expected " + i + ", got " + j);
- }
- }
-
- stream.close();
- clientSocket.close();
- serverSocket.close();
-
- } catch (Exception ex) {
- exception = ex;
- }
- }
-
- public Exception getException() {
- return exception;
- }
-
- public X509Certificate[] getChain() {
- return trustManager.getChain();
- }
-
- }
-
- /**
- * Implements a test SSL socket client. It open a connection to localhost on
- * a given port and writes 256 bytes to the socket.
- */
- class TestClient implements Runnable {
-
- private TestTrustManager trustManager;
-
- private Exception exception;
-
- private int port;
-
- private boolean provideKeys;
-
- public TestClient(int port, boolean provideKeys) {
- this.port = port;
- this.provideKeys = provideKeys;
-
- trustManager = new TestTrustManager();
- }
-
- public void run() {
- try {
- KeyManager[] keyManagers = provideKeys
- ? getKeyManagers(CLIENT_KEYS_BKS) : null;
- TrustManager[] trustManagers = new TrustManager[] {
- trustManager };
-
- SSLContext sslContext = SSLContext.getInstance("TLS");
- sslContext.init(keyManagers, trustManagers, null);
-
- SSLSocket socket = (SSLSocket) sslContext.getSocketFactory()
- .createSocket();
-
- socket.connect(new InetSocketAddress(port));
- socket.startHandshake();
-
- OutputStream stream = socket.getOutputStream();
-
- for (int i = 0; i < 256; i++) {
- stream.write(i);
- }
-
- stream.flush();
- stream.close();
- socket.close();
-
- } catch (Exception ex) {
- exception = ex;
- }
- }
-
- public Exception getException() {
- return exception;
- }
-
- public X509Certificate[] getChain() {
- return trustManager.getChain();
- }
-
- }
-
- /**
- * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
- * for the result.
- */
- private KeyManager[] getKeyManagers(String keys) throws Exception {
- byte[] bytes = new Base64().decode(keys.getBytes());
- InputStream inputStream = new ByteArrayInputStream(bytes);
-
- KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- keyStore.load(inputStream, PASSWORD.toCharArray());
- inputStream.close();
-
- String algorithm = KeyManagerFactory.getDefaultAlgorithm();
- KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
- keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
-
- return keyManagerFactory.getKeyManagers();
- }
-
- /**
- * Implements the actual test case. Launches a server and a client, requires
- * client authentication and checks the certificates afterwards (not in the
- * usual sense, we just make sure that we got the expected certificates,
- * because our self-signed test certificates are not valid.)
- */
- public void testClientAuth() {
- try {
- TestServer server = new TestServer(8088, true, TestServer.CLIENT_AUTH_WANTED);
- TestClient client = new TestClient(8088, true);
-
- Thread serverThread = new Thread(server);
- Thread clientThread = new Thread(client);
-
- serverThread.start();
- clientThread.start();
-
- serverThread.join();
- clientThread.join();
-
- // The server must have completed without an exception.
- if (server.getException() != null) {
- throw new RuntimeException(server.getException());
- }
-
- // The client must have completed without an exception.
- if (client.getException() != null) {
- throw new RuntimeException(client.getException());
- }
-
- // Caution: The clientChain is the certificate chain from our
- // client object. It contains the server certificates, of course!
- X509Certificate[] clientChain = client.getChain();
- assertTrue("Client cert chain must not be null", clientChain != null);
- assertTrue("Client cert chain must not be empty", clientChain.length != 0);
- assertEquals("CN=Test Server, OU=Android, O=Google, L=MTV, ST=California, C=US", clientChain[0].getSubjectDN().toString());
- // Important part ------^
-
- // Caution: The serverChain is the certificate chain from our
- // server object. It contains the client certificates, of course!
- X509Certificate[] serverChain = server.getChain();
- assertTrue("Server cert chain must not be null", serverChain != null);
- assertTrue("Server cert chain must not be empty", serverChain.length != 0);
- assertEquals("CN=Test Client, OU=Android, O=Google, L=MTV, ST=California, C=US", serverChain[0].getSubjectDN().toString());
- // Important part ------^
-
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- // -------------------------------------------------------------------------
- private SSLSocket handshakeSocket;
-
- private Exception handshakeException;
-
-
- public void testSSLHandshakeHangTimeout() {
-
- Thread thread = new Thread() {
- @Override
- public void run() {
- try {
- SSLSocket socket = (SSLSocket)clientFactory.createSocket(
- "www.heise.de", 80);
- socket.setSoTimeout(5000);
- socket.startHandshake();
- socket.close();
- } catch (Exception ex) {
- handshakeException = ex;
- }
- }
- };
-
- thread.start();
-
- try {
- thread.join(10000);
- } catch (InterruptedException ex) {
- // Ignore.
- }
-
- if (handshakeException == null) {
- fail("SSL handshake should have failed.");
- }
- }
-
- public void testSSLHandshakeHangClose() {
-
- Thread thread = new Thread() {
- @Override
- public void run() {
- try {
- handshakeSocket = (SSLSocket)clientFactory.createSocket(
- "www.heise.de", 80);
- handshakeSocket.startHandshake();
- } catch (Exception ex) {
- handshakeException = ex;
- }
- }
- };
-
- thread.start();
-
-
- try {
- Thread.sleep(5000);
- try {
- handshakeSocket.close();
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
-
- thread.join(5000);
- } catch (InterruptedException ex) {
- // Ignore.
- }
-
- if (handshakeException == null) {
- fail("SSL handshake should have failed.");
- }
- }
-
- /**
- * Tests our in-memory and persistent caching support.
- */
- public void testClientSessionCaching() throws IOException,
- KeyManagementException {
- OpenSSLContextImpl context = OpenSSLContextImpl.getPreferred();
-
- // Cache size = 2.
- FakeClientSessionCache fakeCache = new FakeClientSessionCache();
- context.engineInit(null, null, null);
- context.engineGetClientSessionContext().setPersistentCache(fakeCache);
- SSLSocketFactory socketFactory = context.engineGetSocketFactory();
- context.engineGetClientSessionContext().setSessionCacheSize(2);
- makeRequests(socketFactory);
- List<String> smallCacheOps = Arrays.asList(
- "get www.fortify.net",
- "put www.fortify.net",
- "get www.paypal.com",
- "put www.paypal.com",
- "get www.yellownet.ch",
- "put www.yellownet.ch",
-
- // At this point, all in-memory cache requests should miss,
- // but the sessions will still be in the persistent cache.
- "get www.fortify.net",
- "get www.paypal.com",
- "get www.yellownet.ch"
- );
- assertEquals(smallCacheOps, fakeCache.ops);
-
- // Cache size = 3.
- fakeCache = new FakeClientSessionCache();
- context.engineInit(null, null, null);
- context.engineGetClientSessionContext().setPersistentCache(fakeCache);
- socketFactory = context.engineGetSocketFactory();
- context.engineGetClientSessionContext().setSessionCacheSize(3);
- makeRequests(socketFactory);
- List<String> bigCacheOps = Arrays.asList(
- "get www.fortify.net",
- "put www.fortify.net",
- "get www.paypal.com",
- "put www.paypal.com",
- "get www.yellownet.ch",
- "put www.yellownet.ch"
-
- // At this point, all results should be in the in-memory
- // cache, and the persistent cache shouldn't be hit anymore.
- );
- assertEquals(bigCacheOps, fakeCache.ops);
-
- // Cache size = 4.
- fakeCache = new FakeClientSessionCache();
- context.engineInit(null, null, null);
- context.engineGetClientSessionContext().setPersistentCache(fakeCache);
- socketFactory = context.engineGetSocketFactory();
- context.engineGetClientSessionContext().setSessionCacheSize(4);
- makeRequests(socketFactory);
- assertEquals(bigCacheOps, fakeCache.ops);
- }
-
- /**
- * Executes sequence of requests twice using given socket factory.
- */
- private void makeRequests(SSLSocketFactory socketFactory)
- throws IOException {
- for (int i = 0; i < 2; i++) {
- fetch(socketFactory, "www.fortify.net", 443, true, "/sslcheck.html",
- 1, 1, 0, 60);
- fetch(socketFactory, "www.paypal.com", 443, true, "/",
- 1, 1, 0, 60);
- fetch(socketFactory, "www.yellownet.ch", 443, true, "/",
- 1, 1, 0, 60);
- }
- }
-
- /**
- * Fake in the sense that it doesn't actually persist anything.
- */
- static class FakeClientSessionCache implements SSLClientSessionCache {
-
- List<String> ops = new ArrayList<String>();
- Map<String, byte[]> sessions = new HashMap<String, byte[]>();
-
- public byte[] getSessionData(String host, int port) {
- ops.add("get " + host);
- return sessions.get(host);
- }
-
- public void putSessionData(SSLSession session, byte[] sessionData) {
- String host = session.getPeerHost();
- System.err.println("length: " + sessionData.length);
- ops.add("put " + host);
- sessions.put(host, sessionData);
- }
- }
-
- public void testFileBasedClientSessionCache() throws IOException,
- KeyManagementException {
- OpenSSLContextImpl context = OpenSSLContextImpl.getPreferred();
- String tmpDir = System.getProperty("java.io.tmpdir");
- if (tmpDir == null) {
- fail("Please set 'java.io.tmpdir' system property.");
- }
- File cacheDir = new File(tmpDir
- + "/" + SSLSocketTest.class.getName() + "/cache");
- deleteDir(cacheDir);
- SSLClientSessionCache fileCache
- = FileClientSessionCache.usingDirectory(cacheDir);
- try {
- ClientSessionCacheProxy cacheProxy
- = new ClientSessionCacheProxy(fileCache);
- context.engineInit(null, null, null);
- context.engineGetClientSessionContext().setPersistentCache(cacheProxy);
- SSLSocketFactory socketFactory = context.engineGetSocketFactory();
- context.engineGetClientSessionContext().setSessionCacheSize(1);
- makeRequests(socketFactory);
- List<String> expected = Arrays.asList(
- "unsuccessful get www.fortify.net",
- "put www.fortify.net",
- "unsuccessful get www.paypal.com",
- "put www.paypal.com",
- "unsuccessful get www.yellownet.ch",
- "put www.yellownet.ch",
-
- // At this point, all in-memory cache requests should miss,
- // but the sessions will still be in the persistent cache.
- "successful get www.fortify.net",
- "successful get www.paypal.com",
- "successful get www.yellownet.ch"
- );
- assertEquals(expected, cacheProxy.ops);
-
- // Try again now that file-based cache is populated.
- fileCache = FileClientSessionCache.usingDirectory(cacheDir);
- cacheProxy = new ClientSessionCacheProxy(fileCache);
- context.engineInit(null, null, null);
- context.engineGetClientSessionContext().setPersistentCache(cacheProxy);
- socketFactory = context.engineGetSocketFactory();
- context.engineGetClientSessionContext().setSessionCacheSize(1);
- makeRequests(socketFactory);
- expected = Arrays.asList(
- "successful get www.fortify.net",
- "successful get www.paypal.com",
- "successful get www.yellownet.ch",
- "successful get www.fortify.net",
- "successful get www.paypal.com",
- "successful get www.yellownet.ch"
- );
- assertEquals(expected, cacheProxy.ops);
- } finally {
- deleteDir(cacheDir);
- }
- }
-
- private static void deleteDir(File directory) {
- if (!directory.exists()) {
- return;
- }
- for (File file : directory.listFiles()) {
- file.delete();
- }
- directory.delete();
- }
-
- static class ClientSessionCacheProxy implements SSLClientSessionCache {
-
- final SSLClientSessionCache delegate;
- final List<String> ops = new ArrayList<String>();
-
- ClientSessionCacheProxy(SSLClientSessionCache delegate) {
- this.delegate = delegate;
- }
-
- public byte[] getSessionData(String host, int port) {
- byte[] sessionData = delegate.getSessionData(host, port);
- ops.add((sessionData == null ? "unsuccessful" : "successful")
- + " get " + host);
- return sessionData;
- }
-
- public void putSessionData(SSLSession session, byte[] sessionData) {
- delegate.putSessionData(session, sessionData);
- ops.add("put " + session.getPeerHost());
- }
- }
-
- public static void main(String[] args) throws KeyManagementException, IOException {
- new SSLSocketTest().testFileBasedClientSessionCache();
- }
-}
diff --git a/tests/CoreTests/android/core/SocketTest.java b/tests/CoreTests/android/core/SocketTest.java
deleted file mode 100644
index 9db6077..0000000
--- a/tests/CoreTests/android/core/SocketTest.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.core;
-
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.nio.channels.SocketChannel;
-import java.util.concurrent.Semaphore;
-
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
-
-/**
- * Regression tests for various socket related problems. And a few general
- * socket tests.
- */
-public class SocketTest extends TestCase {
-
- private static final String NON_EXISTING_ADDRESS = "123.123.123.123";
-
- private static final String KNOW_GOOD_ADDRESS = "209.85.129.147";
-
- private static final String PACKAGE_DROPPING_ADDRESS = "191.167.0.1";
-
- // Test for basic bind/connect/accept behavior.
- @SmallTest
- public void testSocketSimple() throws Exception {
- ServerSocket ss;
- Socket s, s1;
- int port;
-
- IOException lastEx = null;
-
- ss = new ServerSocket();
-
- for (port = 9900; port < 9999; port++) {
- try {
- ss.bind(new InetSocketAddress("127.0.0.1", port));
- lastEx = null;
- break;
- } catch (IOException ex) {
- lastEx = ex;
- }
- }
-
- if (lastEx != null) {
- throw lastEx;
- }
-
- s = new Socket("127.0.0.1", port);
-
- s1 = ss.accept();
-
- s.getOutputStream().write(0xa5);
-
- assertEquals(0xa5, s1.getInputStream().read());
-
- s1.getOutputStream().write(0x5a);
- assertEquals(0x5a, s.getInputStream().read());
- }
-
- // Regression test for #820068: Wildcard address
- @SmallTest
- public void testWildcardAddress() throws Exception {
- Socket s2 = new Socket();
- s2.bind(new InetSocketAddress((InetAddress) null, 12345));
- byte[] addr = s2.getLocalAddress().getAddress();
- for (int i = 0; i < 4; i++) {
- assertEquals("Not the wildcard address", 0, addr[i]);
- }
- }
-
- // Regression test for #865753: server sockets not closing properly
- @SmallTest
- public void testServerSocketClose() throws Exception {
- ServerSocket s3 = new ServerSocket(23456);
- s3.close();
- ServerSocket s4 = new ServerSocket(23456);
- s4.close();
- }
-
- // Regression test for #876985: SO_REUSEADDR not working properly
-
- private Exception serverError = null;
-
- @LargeTest
- public void testSetReuseAddress() throws IOException {
- InetSocketAddress addr = new InetSocketAddress(8383);
-
- final ServerSocket serverSock = new ServerSocket();
- serverSock.setReuseAddress(true);
- serverSock.bind(addr);
-
- final Semaphore semThreadEnd = new Semaphore(0);
- new Thread() {
- @Override
- public void run() {
- try {
- Socket sock = serverSock.accept();
- sock.getInputStream().read();
- sock.close();
- } catch (IOException e) {
- serverError = e;
- }
- semThreadEnd.release();
- }
- }.start();
-
- // Give the server a bit of time for startup
- try {
- Thread.sleep(2000);
- } catch (InterruptedException ex) {
- // Ignored.
- }
-
- Socket client = new Socket("localhost", 8383);
- client.getOutputStream().write(1);
- // Just leave this connection open from the client side. It will be
- // closed from the server side so the server stays in the TIME_WAIT
- // state for a while. setReuseAddress() should be able to handle this.
-
- try {
- semThreadEnd.acquire();
- } catch (InterruptedException e) {
- // ignore
- }
- serverSock.close();
-
- ServerSocket serverSock2 = new ServerSocket();
- serverSock2.setReuseAddress(true);
- serverSock2.bind(addr);
- serverSock2.close();
-
- if (serverError != null) {
- throw new RuntimeException("Server must complete without error", serverError);
- }
- }
-
- // Regression for 916701, a wrong exception was thrown after timeout of
- // a ServerSocket.
- @LargeTest
- public void testTimeoutException() throws IOException {
- ServerSocket s = new ServerSocket(9800);
- s.setSoTimeout(2000);
- try {
- s.accept();
- } catch (SocketTimeoutException e) {
- // this is ok.
- }
- }
-
- // Regression for issue 1001980, openening a SocketChannel threw an Exception
- @SmallTest
- public void testNativeSocketChannelOpen() throws IOException {
- SocketChannel.open();
- }
-
-// Regression test for issue 1018016, connecting ignored a set timeout.
-//
-// Disabled because test behaves differently depending on networking
-// environment. It works fine in the emulator and one the device with
-// WLAN, but when 3G comes into play, the possible existence of a
-// proxy makes it fail.
-//
-// @LargeTest
-// public void testSocketSetSOTimeout() throws IOException {
-// Socket sock = new Socket();
-// int timeout = 5000;
-// long start = System.currentTimeMillis();
-// try {
-// sock.connect(new InetSocketAddress(NON_EXISTING_ADDRESS, 80), timeout);
-// } catch (SocketTimeoutException e) {
-// // expected
-// long delay = System.currentTimeMillis() - start;
-// if (Math.abs(delay - timeout) > 1000) {
-// fail("timeout was not accurate. expected: " + timeout
-// + " actual: " + delay + " miliseconds.");
-// }
-// } finally {
-// try {
-// sock.close();
-// } catch (IOException ioe) {
-// // ignore
-// }
-// }
-// }
-
- /**
- * Regression test for 1062928: Dotted IP addresses (e.g., 192.168.100.1)
- * appear to be broken in the M5 SDK.
- *
- * Tests that a connection given a ip-addressv4 such as 192.168.100.100 does
- * not fail - sdk m5 seems only to accept dns names instead of ip numbers.
- * ip 209.85.129.147 (one address of www.google.com) on port 80 (http) is
- * used to test the connection.
- */
-
-// Commenting out this test since it is flaky, even at the best of times. See
-// #1191317 for Info.
- @Suppress
- public void disable_testConnectWithIP4IPAddr() {
- // call a Google Web server
- InetSocketAddress scktAddrss = new InetSocketAddress(KNOW_GOOD_ADDRESS,
- 80);
- Socket clntSckt = new Socket();
- try {
- clntSckt.connect(scktAddrss, 5000);
- } catch (Throwable e) {
- fail("connection problem:" + e.getClass().getName() + ": "
- + e.getMessage());
- } finally {
- try {
- clntSckt.close();
- } catch (Exception e) {
- // ignore
- }
- }
- }
-
-
- // Regression test for #1058962: Socket.close() does not cause
- // socket.connect() to return immediately.
- private Socket client;
-
- private Exception error;
-
- private boolean connected;
-
-// This test isn't working now, but really should work.
-// TODO Enable this test again.
-
- @Suppress
- public void disable_testSocketConnectClose() {
- try {
- client = new Socket();
-
- new Thread() {
- @Override
- public void run() {
- try {
- client.connect(new InetSocketAddress(PACKAGE_DROPPING_ADDRESS, 1357));
- } catch (Exception ex) {
- error = ex;
- }
-
- connected = true;
- }
- }.start();
-
- Thread.sleep(1000);
-
- Assert.assertNull("Connect must not fail immediately. Maybe try different address.", error);
- Assert.assertFalse("Connect must not succeed. Maybe try different address.", connected);
-
- client.close();
-
- Thread.sleep(1000);
-
- if (error == null) {
- fail("Socket connect still ongoing");
- } else if (!(error instanceof SocketException)) {
- fail("Socket connect interrupted with wrong error: " + error.toString());
- }
-
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
-
- }
-
-}