Tracking rebase to jb-mr1-release
Change-Id: Ic2ae1a27682cc4152003a68d59068b2c5c5eb09b
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index 8556cc8..9ed763c 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -1329,6 +1329,7 @@
"Landroid/net/Uri$StringUri;", // Requires Uri.
"Landroid/net/WebAddress;", // Calls regex.Pattern.compile -..-> regex.Pattern.compileImpl.
"Landroid/nfc/NdefRecord;", // Calls String.getBytes -> java.nio.charset.Charset.
+ "Landroid/opengl/EGL14;", // Calls android.opengl.EGL14._nativeClassInit.
"Landroid/opengl/GLES10;", // Calls android.opengl.GLES10._nativeClassInit.
"Landroid/opengl/GLES10Ext;", // Calls android.opengl.GLES10Ext._nativeClassInit.
"Landroid/opengl/GLES11;", // Requires GLES10.
@@ -1350,6 +1351,7 @@
"Landroid/server/BluetoothService;", // Calls android.server.BluetoothService.classInitNative.
"Landroid/server/BluetoothEventLoop;", // Calls android.server.BluetoothEventLoop.classInitNative.
"Landroid/telephony/PhoneNumberUtils;", // Calls regex.Pattern.compile -..-> regex.Pattern.compileImpl.
+ "Landroid/telephony/TelephonyManager;", // Calls OsConstants.initConstants.
"Landroid/text/AutoText;", // Requires android.util.DisplayMetrics -..-> android.os.SystemProperties.native_get_int.
"Landroid/text/Layout;", // Calls com.android.internal.util.ArrayUtils.emptyArray -> System.identityHashCode.
"Landroid/text/BoringLayout;", // Requires Layout.
diff --git a/src/compiler/driver/compiler_driver_test.cc b/src/compiler/driver/compiler_driver_test.cc
index dee448d..cbfc2ae 100644
--- a/src/compiler/driver/compiler_driver_test.cc
+++ b/src/compiler/driver/compiler_driver_test.cc
@@ -44,7 +44,8 @@
LOCKS_EXCLUDED(Locks::mutator_lock_) {
CompileAll(class_loader);
Thread::Current()->TransitionFromSuspendedToRunnable();
- runtime_->Start();
+ bool started = runtime_->Start();
+ CHECK(started);
env_ = Thread::Current()->GetJniEnv();
class_ = env_->FindClass(class_name);
CHECK(class_ != NULL) << "Class not found: " << class_name;
diff --git a/src/compiler/jni/jni_compiler_test.cc b/src/compiler/jni/jni_compiler_test.cc
index 5176752..77dd51e 100644
--- a/src/compiler/jni/jni_compiler_test.cc
+++ b/src/compiler/jni/jni_compiler_test.cc
@@ -75,7 +75,8 @@
CompileForTest(class_loader_, direct, method_name, method_sig);
// Start runtime.
Thread::Current()->TransitionFromSuspendedToRunnable();
- runtime_->Start();
+ bool started = runtime_->Start();
+ CHECK(started);
}
// JNI operations after runtime start.
env_ = Thread::Current()->GetJniEnv();
@@ -532,7 +533,8 @@
}
// Start runtime to avoid re-initialization in SetupForTest.
Thread::Current()->TransitionFromSuspendedToRunnable();
- runtime_->Start();
+ bool started = runtime_->Start();
+ CHECK(started);
gJava_MyClassNatives_foo_calls = 0;
diff --git a/src/compiler/llvm/intrinsic_helper.cc b/src/compiler/llvm/intrinsic_helper.cc
index 39c4a58..ac34f70 100644
--- a/src/compiler/llvm/intrinsic_helper.cc
+++ b/src/compiler/llvm/intrinsic_helper.cc
@@ -20,8 +20,8 @@
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
+#include <llvm/IRBuilder.h>
#include <llvm/Intrinsics.h>
-#include <llvm/Support/IRBuilder.h>
namespace art {
namespace llvm {
diff --git a/src/compiler/llvm/ir_builder.h b/src/compiler/llvm/ir_builder.h
index 9362a75..32f0bf9 100644
--- a/src/compiler/llvm/ir_builder.h
+++ b/src/compiler/llvm/ir_builder.h
@@ -26,8 +26,8 @@
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
+#include <llvm/IRBuilder.h>
#include <llvm/LLVMContext.h>
-#include <llvm/Support/IRBuilder.h>
#include <llvm/Support/NoFolder.h>
#include <llvm/Type.h>
diff --git a/src/compiler/llvm/llvm_compilation_unit.cc b/src/compiler/llvm/llvm_compilation_unit.cc
index 3783ae9..41c603f 100644
--- a/src/compiler/llvm/llvm_compilation_unit.cc
+++ b/src/compiler/llvm/llvm_compilation_unit.cc
@@ -26,7 +26,6 @@
#include <llvm/ADT/StringSet.h>
#include <llvm/ADT/Triple.h>
#include <llvm/Analysis/CallGraph.h>
-#include <llvm/Analysis/DebugInfo.h>
#include <llvm/Analysis/Dominators.h>
#include <llvm/Analysis/LoopInfo.h>
#include <llvm/Analysis/LoopPass.h>
@@ -39,6 +38,7 @@
#include <llvm/CodeGen/MachineFrameInfo.h>
#include <llvm/CodeGen/MachineFunction.h>
#include <llvm/CodeGen/MachineFunctionPass.h>
+#include <llvm/DebugInfo.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/Module.h>
diff --git a/src/compiler/llvm/md_builder.cc b/src/compiler/llvm/md_builder.cc
index afb3611..657adc5 100644
--- a/src/compiler/llvm/md_builder.cc
+++ b/src/compiler/llvm/md_builder.cc
@@ -17,7 +17,7 @@
#include "md_builder.h"
-#include "llvm/Support/MDBuilder.h"
+#include "llvm/MDBuilder.h"
#include <string>
diff --git a/src/compiler/llvm/md_builder.h b/src/compiler/llvm/md_builder.h
index 5231c14..5272ee5 100644
--- a/src/compiler/llvm/md_builder.h
+++ b/src/compiler/llvm/md_builder.h
@@ -19,7 +19,7 @@
#include "backend_types.h"
-#include "llvm/Support/MDBuilder.h"
+#include "llvm/MDBuilder.h"
#include <cstring>
diff --git a/src/dex_file.cc b/src/dex_file.cc
index e67e767..12c11e8 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -299,7 +299,7 @@
method_ids_ = reinterpret_cast<const MethodId*>(b + h->method_ids_off_);
proto_ids_ = reinterpret_cast<const ProtoId*>(b + h->proto_ids_off_);
class_defs_ = reinterpret_cast<const ClassDef*>(b + h->class_defs_off_);
- DCHECK_EQ(size_, header_->file_size_);
+ DCHECK_EQ(size_, header_->file_size_) << GetLocation();
}
bool DexFile::CheckMagicAndVersion() const {
diff --git a/src/exception_test.cc b/src/exception_test.cc
index 1d32f1b..f0bec1b 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -137,7 +137,8 @@
TEST_F(ExceptionTest, StackTraceElement) {
Thread* thread = Thread::Current();
thread->TransitionFromSuspendedToRunnable();
- runtime_->Start();
+ bool started = runtime_->Start();
+ CHECK(started);
JNIEnv* env = thread->GetJniEnv();
ScopedObjectAccess soa(env);
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 0ee4c21..726c80b 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -2564,7 +2564,13 @@
return JNI_ERR;
}
Runtime* runtime = Runtime::Current();
- runtime->Start();
+ bool started = runtime->Start();
+ if (!started) {
+ delete Thread::Current()->GetJniEnv();
+ delete runtime->GetJavaVM();
+ LOG(WARNING) << "CreateJavaVM failed";
+ return JNI_ERR;
+ }
*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
return JNI_OK;
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index deff290..4b820f9 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -1179,7 +1179,8 @@
TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
Thread::Current()->TransitionFromSuspendedToRunnable();
LoadDex("AllFields");
- runtime_->Start();
+ bool started = runtime_->Start();
+ CHECK(started);
jclass c = env_->FindClass("AllFields");
ASSERT_TRUE(c != NULL);
diff --git a/src/native/dalvik_system_Zygote.cc b/src/native/dalvik_system_Zygote.cc
index d33c67f..9b995f4 100644
--- a/src/native/dalvik_system_Zygote.cc
+++ b/src/native/dalvik_system_Zygote.cc
@@ -14,15 +14,20 @@
* limitations under the License.
*/
+// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
+#include <sys/mount.h>
+#include <linux/fs.h>
+
#include <grp.h>
#include <paths.h>
#include <signal.h>
#include <stdlib.h>
-#include <sys/mount.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
+#include "cutils/fs.h"
+#include "cutils/multiuser.h"
#include "cutils/sched_policy.h"
#include "debugger.h"
#include "jni_internal.h"
@@ -53,6 +58,7 @@
MOUNT_EXTERNAL_NONE = 0,
MOUNT_EXTERNAL_SINGLEUSER = 1,
MOUNT_EXTERNAL_MULTIUSER = 2,
+ MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
};
// This signal handler is for zygote mode, since the zygote must reap its children
@@ -303,45 +309,91 @@
}
}
-// Create private mount space for this process and mount SD card
-// into it, based on the active user.
-static void MountExternalStorage(uid_t uid, jint mount_external) {
- if (mount_external == MOUNT_EXTERNAL_NONE) {
- return;
+// Create a private mount namespace and bind mount appropriate emulated
+// storage for the given user.
+static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
+ if (mount_mode == MOUNT_EXTERNAL_NONE) {
+ return true;
}
-#if 0
- userid_t user_id = multiuser_getUserId(uid);
+ // See storage config details at http://source.android.com/tech/storage/
+ userid_t user_id = multiuser_get_user_id(uid);
- // Create private mount namespace for our process.
+ // Create a second private mount namespace for our process
if (unshare(CLONE_NEWNS) == -1) {
- PLOG(FATAL) << "unshare(CLONE_NEWNS) failed";
+ PLOG(WARNING) << "Failed to unshare()";
+ return false;
}
- // Mark rootfs as being a slave in our process so that changes
- // from parent namespace flow into our process.
- if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) {
- PLOG(FATAL) << "mount(\"rootfs\", \"/\", NULL, (MS_SLAVE | MS_REC), NULL) failed";
- }
-
- // Create bind mount from specific path.
- if (mount_external == MOUNT_EXTERNAL_SINGLEUSER) {
- if (mount(EXTERNAL_STORAGE_SYSTEM, EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
- PLOG(FATAL) << "mount(\"" << EXTERNAL_STORAGE_SYSTEM << "\", \"" << EXTERNAL_STORAGE_APP << "\", \"none\", MS_BIND, NULL) failed";
+ // Create bind mounts to expose external storage
+ if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+ // These paths must already be created by init.rc
+ const char* source = getenv("EMULATED_STORAGE_SOURCE");
+ const char* target = getenv("EMULATED_STORAGE_TARGET");
+ const char* legacy = getenv("EXTERNAL_STORAGE");
+ if (source == NULL || target == NULL || legacy == NULL) {
+ LOG(WARNING) << "Storage environment undefined; unable to provide external storage";
+ return false;
}
- } else if (mount_external == MOUNT_EXTERNAL_MULTIUSER) {
- // Assume path has already been created by installd.
- std::string source_path(StringPrintf("%s/%d", EXTERNAL_STORAGE_SYSTEM, user_id));
- if (mount(source_path.c_str(), EXTERNAL_STORAGE_APP, "none", MS_BIND, NULL) == -1) {
- PLOG(FATAL) << "mount(\"" << source_path.c_str() << "\", \"" << EXTERNAL_STORAGE_APP << "\", \"none\", MS_BIND, NULL) failed";
+
+ // Prepare source paths
+
+ // /mnt/shell/emulated/0
+ std::string source_user(StringPrintf("%s/%d", source, user_id));
+ // /mnt/shell/emulated/obb
+ std::string source_obb(StringPrintf("%s/obb", source));
+ // /storage/emulated/0
+ std::string target_user(StringPrintf("%s/%d", target, user_id));
+
+ if (fs_prepare_dir(source_user.c_str(), 0000, 0, 0) == -1
+ || fs_prepare_dir(source_obb.c_str(), 0000, 0, 0) == -1
+ || fs_prepare_dir(target_user.c_str(), 0000, 0, 0) == -1) {
+ return false;
+ }
+
+ if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+ // Mount entire external storage tree for all users
+ if (mount(source, target, NULL, MS_BIND, NULL) == -1) {
+ PLOG(WARNING) << "Failed to mount " << source << " to " << target;
+ return false;
+ }
+ } else {
+ // Only mount user-specific external storage
+ if (mount(source_user.c_str(), target_user.c_str(), NULL, MS_BIND, NULL) == -1) {
+ PLOG(WARNING) << "Failed to mount " << source_user << " to " << target_user;
+ return false;
+ }
+ }
+
+ // Now that user is mounted, prepare and mount OBB storage
+ // into place for current user
+
+ // /storage/emulated/0/Android
+ std::string target_android(StringPrintf("%s/%d/Android", target, user_id));
+ // /storage/emulated/0/Android/obb
+ std::string target_obb(StringPrintf("%s/%d/Android/obb", target, user_id));
+
+ if (fs_prepare_dir(target_android.c_str(), 0000, 0, 0) == -1
+ || fs_prepare_dir(target_obb.c_str(), 0000, 0, 0) == -1
+ || fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
+ return false;
+ }
+ if (mount(source_obb.c_str(), target_obb.c_str(), NULL, MS_BIND, NULL) == -1) {
+ PLOG(WARNING) << "Failed to mount " << source_obb << " to " << target_obb;
+ return false;
+ }
+
+ // Finally, mount user-specific path into place for legacy users
+ if (mount(target_user.c_str(), legacy, NULL, MS_BIND | MS_REC, NULL) == -1) {
+ PLOG(WARNING) << "Failed to mount " << target_user << " to " << legacy;
+ return false;
}
} else {
- LOG(FATAL) << "Mount mode unsupported: " << mount_external;
+ LOG(WARNING) << "Mount mode " << mount_mode << " unsupported";
+ return false;
}
-#else
- UNUSED(uid);
- UNIMPLEMENTED(FATAL);
-#endif
+
+ return true;
}
#if defined(__linux__)
@@ -397,7 +449,18 @@
DropCapabilitiesBoundingSet();
- MountExternalStorage(uid, mount_external);
+ if (!MountEmulatedStorage(uid, mount_external)) {
+ PLOG(WARNING) << "Failed to mount emulated storage";
+ if (errno == ENOTCONN || errno == EROFS) {
+ // When device is actively encrypting, we get ENOTCONN here
+ // since FUSE was mounted before the framework restarted.
+ // When encrypted device is booting, we get EROFS since
+ // FUSE hasn't been created yet by init.
+ // In either case, continue without external storage.
+ } else {
+ LOG(FATAL) << "Cannot continue without emulated storage";
+ }
+ }
SetGids(env, javaGids);
diff --git a/src/runtime.cc b/src/runtime.cc
index 414bef4..9b2dca7 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -16,6 +16,10 @@
#include "runtime.h"
+// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
+#include <sys/mount.h>
+#include <linux/fs.h>
+
#include <signal.h>
#include <sys/syscall.h>
@@ -472,7 +476,7 @@
double value;
iss >> value;
// Ensure that we have a value, there was no cruft after it and it satisfies a sensible range.
- const bool sane_val = iss.good() && (value >= 0.1) && (value <= 0.9);
+ const bool sane_val = iss.eof() && (value >= 0.1) && (value <= 0.9);
if (!sane_val) {
if (ignore_unrecognized) {
continue;
@@ -640,7 +644,7 @@
contextClassLoader->SetObject(soa.Self()->GetPeer(), class_loader);
}
-void Runtime::Start() {
+bool Runtime::Start() {
VLOG(startup) << "Runtime::Start entering";
CHECK(host_prefix_.empty()) << host_prefix_;
@@ -666,7 +670,11 @@
Thread::FinishStartup();
- if (!is_zygote_) {
+ if (is_zygote_) {
+ if (!InitZygote()) {
+ return false;
+ }
+ } else {
DidForkFromZygote();
}
@@ -679,6 +687,8 @@
VLOG(startup) << "Runtime::Start exiting";
finished_starting_ = true;
+
+ return true;
}
void Runtime::EndThreadBirth() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_) {
@@ -689,6 +699,40 @@
}
}
+// Do zygote-mode-only initialization.
+bool Runtime::InitZygote() {
+ // zygote goes into its own process group
+ setpgid(0,0);
+
+ // See storage config details at http://source.android.com/tech/storage/
+ // Create private mount namespace shared by all children
+ if (unshare(CLONE_NEWNS) == -1) {
+ PLOG(WARNING) << "Failed to unshare()";
+ return false;
+ }
+
+ // Mark rootfs as being a slave so that changes from default
+ // namespace only flow into our children.
+ if (mount("rootfs", "/", NULL, (MS_SLAVE | MS_REC), NULL) == -1) {
+ PLOG(WARNING) << "Failed to mount() rootfs as MS_SLAVE";
+ return false;
+ }
+
+ // Create a staging tmpfs that is shared by our children; they will
+ // bind mount storage into their respective private namespaces, which
+ // are isolated from each other.
+ const char* target_base = getenv("EMULATED_STORAGE_TARGET");
+ if (target_base != NULL) {
+ if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV,
+ "uid=0,gid=1028,mode=0050") == -1) {
+ LOG(WARNING) << "Failed to mount tmpfs to " << target_base;
+ return false;
+ }
+ }
+
+ return true;
+}
+
void Runtime::DidForkFromZygote() {
is_zygote_ = false;
diff --git a/src/runtime.h b/src/runtime.h
index 696f231..f8788ad 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -126,7 +126,7 @@
}
// Starts a runtime, which may cause threads to be started and code to run.
- void Start() UNLOCK_FUNCTION(Locks::mutator_lock_);
+ bool Start() UNLOCK_FUNCTION(Locks::mutator_lock_);
bool IsShuttingDown() const EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_) {
return shutting_down_;
@@ -346,8 +346,9 @@
void SetStatsEnabled(bool new_state);
- void DidForkFromZygote();
bool PreZygoteFork();
+ bool InitZygote();
+ void DidForkFromZygote();
void EnableMethodTracing(Trace* trace);
void DisableMethodTracing();
diff --git a/src/runtime_test.cc b/src/runtime_test.cc
index e147749..d53b4a6 100644
--- a/src/runtime_test.cc
+++ b/src/runtime_test.cc
@@ -46,6 +46,7 @@
options.push_back(std::make_pair("-Xms2048", null));
options.push_back(std::make_pair("-Xmx4k", null));
options.push_back(std::make_pair("-Xss1m", null));
+ options.push_back(std::make_pair("-XX:HeapTargetUtilization=0.75", null));
options.push_back(std::make_pair("-Dfoo=bar", null));
options.push_back(std::make_pair("-Dbaz=qux", null));
options.push_back(std::make_pair("-verbose:gc,class,jni", null));
@@ -63,6 +64,7 @@
EXPECT_EQ(2048U, parsed->heap_initial_size_);
EXPECT_EQ(4 * KB, parsed->heap_maximum_size_);
EXPECT_EQ(1 * MB, parsed->stack_size_);
+ EXPECT_EQ(0.75, parsed->heap_target_utilization_);
EXPECT_EQ("host_prefix", parsed->host_prefix_);
EXPECT_TRUE(test_vfprintf == parsed->hook_vfprintf_);
EXPECT_TRUE(test_exit == parsed->hook_exit_);