summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Brian Carlstrom <bdc@google.com> 2013-03-10 20:26:16 -0700
committer Brian Carlstrom <bdc@google.com> 2013-03-11 15:47:02 -0700
commitbd86bccf1b47f1151842152ee52cf5d46d6b34ab (patch)
treec0c110b47435c6e8548f1b7126f9ea20da7fd934
parent5d021c7399fa8090910d5b47ed00465a4e0e7e0f (diff)
Tracking rebase to jb-mr1-release
Change-Id: Ic2ae1a27682cc4152003a68d59068b2c5c5eb09b
-rw-r--r--src/compiler/driver/compiler_driver.cc2
-rw-r--r--src/compiler/driver/compiler_driver_test.cc3
-rw-r--r--src/compiler/jni/jni_compiler_test.cc6
-rw-r--r--src/compiler/llvm/intrinsic_helper.cc2
-rw-r--r--src/compiler/llvm/ir_builder.h2
-rw-r--r--src/compiler/llvm/llvm_compilation_unit.cc2
-rw-r--r--src/compiler/llvm/md_builder.cc2
-rw-r--r--src/compiler/llvm/md_builder.h2
-rw-r--r--src/dex_file.cc2
-rw-r--r--src/exception_test.cc3
-rw-r--r--src/jni_internal.cc8
-rw-r--r--src/jni_internal_test.cc3
-rw-r--r--src/native/dalvik_system_Zygote.cc123
-rw-r--r--src/runtime.cc50
-rw-r--r--src/runtime.h5
-rw-r--r--src/runtime_test.cc2
16 files changed, 170 insertions, 47 deletions
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index 8556cc8366..9ed763cdfd 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -1329,6 +1329,7 @@ static const char* class_initializer_black_list[] = {
"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 @@ static const char* class_initializer_black_list[] = {
"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 dee448d33f..cbfc2ae948 100644
--- a/src/compiler/driver/compiler_driver_test.cc
+++ b/src/compiler/driver/compiler_driver_test.cc
@@ -44,7 +44,8 @@ class CompilerDriverTest : public CommonTest {
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 5176752a9d..77dd51ef6f 100644
--- a/src/compiler/jni/jni_compiler_test.cc
+++ b/src/compiler/jni/jni_compiler_test.cc
@@ -75,7 +75,8 @@ class JniCompilerTest : public CommonTest {
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 @@ TEST_F(JniCompilerTest, ExceptionHandling) {
}
// 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 39c4a586e2..ac34f7078f 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 9362a751da..32f0bf9696 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 3783ae99e0..41c603f349 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 afb36111eb..657adc5f11 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 5231c14f07..5272ee5a95 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 e67e767dba..12c11e8c91 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -299,7 +299,7 @@ void DexFile::InitMembers() {
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 1d32f1bb6a..f0bec1b2c3 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -137,7 +137,8 @@ TEST_F(ExceptionTest, FindCatchHandler) {
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 0ee4c21ce4..726c80bbe0 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -2564,7 +2564,13 @@ extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, void** p_env, void* vm_args) {
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 deff290c33..4b820f9126 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -1179,7 +1179,8 @@ TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
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 d33c67fb0e..9b995f421d 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 @@ enum MountExternalKind {
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 @@ static void EnableDebugFeatures(uint32_t debug_flags) {
}
}
-// 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 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;
+ }
+
+ // 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));
- // 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";
+ 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;
}
- } 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";
+
+ 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 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
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 414bef4093..9b2dca72a4 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 @@ Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, b
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 @@ static void CreateSystemClassLoader() {
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 @@ void Runtime::Start() {
Thread::FinishStartup();
- if (!is_zygote_) {
+ if (is_zygote_) {
+ if (!InitZygote()) {
+ return false;
+ }
+ } else {
DidForkFromZygote();
}
@@ -679,6 +687,8 @@ void Runtime::Start() {
VLOG(startup) << "Runtime::Start exiting";
finished_starting_ = true;
+
+ return true;
}
void Runtime::EndThreadBirth() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_) {
@@ -689,6 +699,40 @@ void Runtime::EndThreadBirth() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_
}
}
+// 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 696f2317e9..f8788ad934 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -126,7 +126,7 @@ class Runtime {
}
// 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 @@ class Runtime {
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 e147749346..d53b4a62a1 100644
--- a/src/runtime_test.cc
+++ b/src/runtime_test.cc
@@ -46,6 +46,7 @@ TEST_F(RuntimeTest, ParsedOptions) {
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 @@ TEST_F(RuntimeTest, ParsedOptions) {
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_);