Merge "Pass correct is_static to ResolveField."
diff --git a/Android.mk b/Android.mk
index 8e43879..62d40bb 100644
--- a/Android.mk
+++ b/Android.mk
@@ -92,7 +92,6 @@
include $(art_path)/disassembler/Android.mk
include $(art_path)/oatdump/Android.mk
include $(art_path)/dalvikvm/Android.mk
-include $(art_path)/tools/Android.mk
include $(art_build_path)/Android.oat.mk
# ART_HOST_DEPENDENCIES depends on Android.executable.mk above for ART_HOST_EXECUTABLES
@@ -301,12 +300,6 @@
.PHONY: build-art-target
build-art-target: $(ART_TARGET_EXECUTABLES) $(ART_TARGET_TEST_EXECUTABLES) $(TARGET_CORE_IMG_OUT) $(TARGET_OUT)/lib/libjavacore.so
-.PHONY: art-host
-art-host: $(HOST_OUT_EXECUTABLES)/art $(HOST_OUT)/bin/dalvikvm $(HOST_OUT)/lib/libart.so $(HOST_OUT)/bin/dex2oat $(HOST_OUT_JAVA_LIBRARIES)/core.art $(HOST_OUT)/lib/libjavacore.so
-
-.PHONY: art-host-debug
-art-host-debug: art-host $(HOST_OUT)/lib/libartd.so $(HOST_OUT)/bin/dex2oatd
-
########################################################################
# oatdump targets
diff --git a/compiler/dex/quick/mir_to_lir-inl.h b/compiler/dex/quick/mir_to_lir-inl.h
index f567b5c..c2d12f6 100644
--- a/compiler/dex/quick/mir_to_lir-inl.h
+++ b/compiler/dex/quick/mir_to_lir-inl.h
@@ -98,6 +98,16 @@
return insn;
}
+inline LIR* Mir2Lir::NewLIR2NoDest(int opcode, int src, int info) {
+ DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_UNARY_OP))
+ << GetTargetInstName(opcode) << " " << opcode << " "
+ << PrettyMethod(cu_->method_idx, *cu_->dex_file) << " "
+ << current_dalvik_offset_;
+ LIR* insn = RawLIR(current_dalvik_offset_, opcode, src, info);
+ AppendLIR(insn);
+ return insn;
+}
+
inline LIR* Mir2Lir::NewLIR3(int opcode, int dest, int src1, int src2) {
DCHECK(IsPseudoLirOp(opcode) || (GetTargetInstFlags(opcode) & IS_TERTIARY_OP))
<< GetTargetInstName(opcode) << " " << opcode << " "
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 6115953..5d4439f 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -401,6 +401,7 @@
LIR* NewLIR0(int opcode);
LIR* NewLIR1(int opcode, int dest);
LIR* NewLIR2(int opcode, int dest, int src1);
+ LIR* NewLIR2NoDest(int opcode, int src, int info);
LIR* NewLIR3(int opcode, int dest, int src1, int src2);
LIR* NewLIR4(int opcode, int dest, int src1, int src2, int info);
LIR* NewLIR5(int opcode, int dest, int src1, int src2, int info1, int info2);
@@ -480,6 +481,7 @@
virtual void ResetDefLocWide(RegLocation rl);
void ResetDefTracking();
void ClobberAllRegs();
+ void FlushSpecificReg(RegisterInfo* info);
void FlushAllRegsBody(RegisterInfo* info, int num_regs);
void FlushAllRegs();
bool RegClassMatches(int reg_class, int reg);
diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc
index eb70d8c..0a65171 100644
--- a/compiler/dex/quick/ralloc_util.cc
+++ b/compiler/dex/quick/ralloc_util.cc
@@ -545,15 +545,19 @@
}
}
+void Mir2Lir::FlushSpecificReg(RegisterInfo* info) {
+ if (info->pair) {
+ FlushRegWide(info->reg, info->partner);
+ } else {
+ FlushReg(info->reg);
+ }
+}
+
// Make sure nothing is live and dirty
void Mir2Lir::FlushAllRegsBody(RegisterInfo* info, int num_regs) {
for (int i = 0; i < num_regs; i++) {
if (info[i].live && info[i].dirty) {
- if (info[i].pair) {
- FlushRegWide(info[i].reg, info[i].partner);
- } else {
- FlushReg(info[i].reg);
- }
+ FlushSpecificReg(&info[i]);
}
}
}
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index 321c6a7..6481589 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -295,7 +295,11 @@
{ kX86PsrlqRI, kRegImm, IS_BINARY_OP | REG_DEF0_USE0, { 0x66, 0, 0x0F, 0x73, 0, 2, 0, 1 }, "PsrlqRI", "!0r,!1d" },
{ kX86PsllqRI, kRegImm, IS_BINARY_OP | REG_DEF0_USE0, { 0x66, 0, 0x0F, 0x73, 0, 6, 0, 1 }, "PsllqRI", "!0r,!1d" },
{ kX86SqrtsdRR, kRegReg, IS_BINARY_OP | REG_DEF0_USE1, { 0xF2, 0, 0x0F, 0x51, 0, 0, 0, 0 }, "SqrtsdRR", "!0r,!1r" },
- { kX86FstpdM, kMem, IS_STORE | IS_BINARY_OP | REG_USE0, { 0x0, 0, 0xDD, 0x00, 0, 3, 0, 0 }, "FstpdM", "[!0r,!1d]" },
+
+ { kX86Fild32M, kMem, IS_LOAD | IS_UNARY_OP | REG_USE0, { 0x0, 0, 0xDB, 0x00, 0, 0, 0, 0 }, "Fild32M", "[!0r,!1d]" },
+ { kX86Fild64M, kMem, IS_LOAD | IS_UNARY_OP | REG_USE0, { 0x0, 0, 0xDF, 0x00, 0, 5, 0, 0 }, "Fild64M", "[!0r,!1d]" },
+ { kX86Fstp32M, kMem, IS_STORE | IS_UNARY_OP | REG_USE0, { 0x0, 0, 0xD9, 0x00, 0, 3, 0, 0 }, "FstpdM", "[!0r,!1d]" },
+ { kX86Fstp64M, kMem, IS_STORE | IS_UNARY_OP | REG_USE0, { 0x0, 0, 0xDD, 0x00, 0, 3, 0, 0 }, "FstpdM", "[!0r,!1d]" },
EXT_0F_ENCODING_MAP(Movups, 0x0, 0x10, REG_DEF0),
{ kX86MovupsMR, kMemReg, IS_STORE | IS_TERTIARY_OP | REG_USE02, { 0x0, 0, 0x0F, 0x11, 0, 0, 0, 0 }, "MovupsMR", "[!0r+!1d],!2r" },
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 22e36d5..70263d8 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -452,6 +452,7 @@
*/
LIR* OpCmpMemImmBranch(ConditionCode cond, int temp_reg, int base_reg,
int offset, int check_value, LIR* target);
+
/*
* Can this operation be using core registers without temporaries?
* @param rl_lhs Left hand operand.
@@ -460,6 +461,14 @@
*/
bool IsOperationSafeWithoutTemps(RegLocation rl_lhs, RegLocation rl_rhs);
+ /**
+ * @brief Generates inline code for conversion of long to FP by using x87/
+ * @param rl_dest The destination of the FP.
+ * @param rl_src The source of the long.
+ * @param is_double 'true' if dealing with double, 'false' for float.
+ */
+ void GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double);
+
/*
* @brief Perform MIR analysis before compiling method.
* @note Invokes Mir2LiR::Materialize after analysis.
diff --git a/compiler/dex/quick/x86/fp_x86.cc b/compiler/dex/quick/x86/fp_x86.cc
index 006fe76..4c2ecc0 100644
--- a/compiler/dex/quick/x86/fp_x86.cc
+++ b/compiler/dex/quick/x86/fp_x86.cc
@@ -130,6 +130,70 @@
StoreValueWide(rl_dest, rl_result);
}
+void X86Mir2Lir::GenLongToFP(RegLocation rl_dest, RegLocation rl_src, bool is_double) {
+ // Compute offsets to the source and destination VRs on stack
+ int src_v_reg_offset = SRegOffset(rl_src.s_reg_low);
+ int dest_v_reg_offset = SRegOffset(rl_dest.s_reg_low);
+
+ // Update the in-register state of source.
+ rl_src = UpdateLocWide(rl_src);
+
+ // If the source is in physical register, then put it in its location on stack.
+ if (rl_src.location == kLocPhysReg) {
+ RegisterInfo* lo_info = GetRegInfo(rl_src.low_reg);
+
+ if (lo_info != nullptr && lo_info->is_temp) {
+ // Calling FlushSpecificReg because it will only write back VR if it is dirty.
+ FlushSpecificReg(lo_info);
+ } else {
+ // It must have been register promoted if it is not a temp but is still in physical
+ // register. Since we need it to be in memory to convert, we place it there now.
+ StoreBaseDispWide(TargetReg(kSp), src_v_reg_offset, rl_src.low_reg, rl_src.high_reg);
+ }
+ }
+
+ // Push the source virtual register onto the x87 stack.
+ LIR *fild64 = NewLIR2NoDest(kX86Fild64M, TargetReg(kSp), src_v_reg_offset + LOWORD_OFFSET);
+ AnnotateDalvikRegAccess(fild64, (src_v_reg_offset + LOWORD_OFFSET) >> 2,
+ true /* is_load */, true /* is64bit */);
+
+ // Now pop off x87 stack and store it in the destination VR's stack location.
+ int opcode = is_double ? kX86Fstp64M : kX86Fstp32M;
+ int displacement = is_double ? dest_v_reg_offset + LOWORD_OFFSET : dest_v_reg_offset;
+ LIR *fstp = NewLIR2NoDest(opcode, TargetReg(kSp), displacement);
+ AnnotateDalvikRegAccess(fstp, displacement >> 2, false /* is_load */, is_double);
+
+ /*
+ * The result is in a physical register if it was in a temp or was register
+ * promoted. For that reason it is enough to check if it is in physical
+ * register. If it is, then we must do all of the bookkeeping necessary to
+ * invalidate temp (if needed) and load in promoted register (if needed).
+ * If the result's location is in memory, then we do not need to do anything
+ * more since the fstp has already placed the correct value in memory.
+ */
+ RegLocation rl_result = is_double ? UpdateLocWide(rl_dest) : UpdateLoc(rl_dest);
+ if (rl_result.location == kLocPhysReg) {
+ /*
+ * We already know that the result is in a physical register but do not know if it is the
+ * right class. So we call EvalLoc(Wide) first which will ensure that it will get moved to the
+ * correct register class.
+ */
+ if (is_double) {
+ rl_result = EvalLocWide(rl_dest, kFPReg, true);
+
+ LoadBaseDispWide(TargetReg(kSp), dest_v_reg_offset, rl_result.low_reg, rl_result.high_reg, INVALID_SREG);
+
+ StoreValueWide(rl_dest, rl_result);
+ } else {
+ rl_result = EvalLoc(rl_dest, kFPReg, true);
+
+ LoadWordDisp(TargetReg(kSp), dest_v_reg_offset, rl_result.low_reg);
+
+ StoreValue(rl_dest, rl_result);
+ }
+ }
+}
+
void X86Mir2Lir::GenConversion(Instruction::Code opcode, RegLocation rl_dest,
RegLocation rl_src) {
RegisterClass rcSrc = kFPReg;
@@ -198,11 +262,10 @@
return;
}
case Instruction::LONG_TO_DOUBLE:
- GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pL2d), rl_dest, rl_src);
+ GenLongToFP(rl_dest, rl_src, true /* is_double */);
return;
case Instruction::LONG_TO_FLOAT:
- // TODO: inline by using memory as a 64-bit source. Be careful about promoted registers.
- GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pL2f), rl_dest, rl_src);
+ GenLongToFP(rl_dest, rl_src, false /* is_double */);
return;
case Instruction::FLOAT_TO_LONG:
GenConversionCall(QUICK_ENTRYPOINT_OFFSET(pF2l), rl_dest, rl_src);
diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h
index 8c385a1..480d5f5 100644
--- a/compiler/dex/quick/x86/x86_lir.h
+++ b/compiler/dex/quick/x86/x86_lir.h
@@ -355,7 +355,10 @@
kX86PsrlqRI, // right shift of floating point registers
kX86PsllqRI, // left shift of floating point registers
kX86SqrtsdRR, // sqrt of floating point register
- kX86FstpdM, // Store and pop top x87 fp stack
+ kX86Fild32M, // push 32-bit integer on x87 stack
+ kX86Fild64M, // push 64-bit integer on x87 stack
+ kX86Fstp32M, // pop top x87 fp stack and do 32-bit store
+ kX86Fstp64M, // pop top x87 fp stack and do 64-bit store
Binary0fOpCode(kX86Movups), // load unaligned packed single FP values from xmm2/m128 to xmm1
kX86MovupsMR, kX86MovupsAR, // store unaligned packed single FP values from xmm1 to m128
Binary0fOpCode(kX86Movaps), // load aligned packed single FP values from xmm2/m128 to xmm1
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 9bfd170..5b22817 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1006,7 +1006,7 @@
uint32_t method_idx = verifier->GetMethodReference().dex_method_index;
mirror::ArtMethod* method = dex_cache->GetResolvedMethod(method_idx);
mirror::ArtField* field = dex_cache->GetResolvedField(field_idx);
- if (method == nullptr || field == nullptr) {
+ if (method == nullptr || field == nullptr || field->IsStatic()) {
return false;
}
mirror::Class* method_class = method->GetDeclaringClass();
@@ -2111,6 +2111,7 @@
"Ljava/net/Inet6Address;", // Sub-class of InetAddress.
"Ljava/net/InetUnixAddress;", // Sub-class of InetAddress.
"Ljava/net/NetworkInterface;", // Calls to Random.<init> -> System.currentTimeMillis -> OsConstants.initConstants.
+ "Ljava/net/StandardSocketOptions;", // Call System.identityHashCode.
"Ljava/nio/charset/Charset;", // Calls Charset.getDefaultCharset -> System.getProperty -> OsConstants.initConstants.
"Ljava/nio/charset/CharsetICU;", // Sub-class of Charset.
"Ljava/nio/charset/Charsets;", // Calls Charset.forName.
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index 903d755..b6ddc95 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -672,6 +672,13 @@
has_modrm = true;
reg_is_opcode = true;
break;
+ case 0xDB:
+ static const char* db_opcodes[] = {"fildl", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db", "unknown-db"};
+ modrm_opcodes = db_opcodes;
+ load = true;
+ has_modrm = true;
+ reg_is_opcode = true;
+ break;
case 0xDD:
static const char* dd_opcodes[] = {"fldl", "fisttp", "fstl", "fstpl", "frstor", "unknown-dd", "fnsave", "fnstsw"};
modrm_opcodes = dd_opcodes;
@@ -679,6 +686,13 @@
has_modrm = true;
reg_is_opcode = true;
break;
+ case 0xDF:
+ static const char* df_opcodes[] = {"fild", "unknown-df", "unknown-df", "unknown-df", "unknown-df", "fildll", "unknown-df", "unknown-df"};
+ modrm_opcodes = df_opcodes;
+ load = true;
+ has_modrm = true;
+ reg_is_opcode = true;
+ break;
case 0xE8: opcode << "call"; branch_bytes = 4; break;
case 0xE9: opcode << "jmp"; branch_bytes = 4; break;
case 0xEB: opcode << "jmp"; branch_bytes = 1; break;
diff --git a/runtime/native/dalvik_system_Zygote.cc b/runtime/native/dalvik_system_Zygote.cc
index 22c5430..7e6432e 100644
--- a/runtime/native/dalvik_system_Zygote.cc
+++ b/runtime/native/dalvik_system_Zygote.cc
@@ -23,8 +23,10 @@
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <fcntl.h>
#include "cutils/fs.h"
#include "cutils/multiuser.h"
@@ -406,13 +408,43 @@
}
#endif
+// Utility to close down the Zygote socket file descriptors while
+// the child is still running as root with Zygote's privileges. Each
+// descriptor (if any) is closed via dup2(), replacing it with a valid
+// (open) descriptor to /dev/null.
+
+static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
+ if (!fdsToClose) {
+ return;
+ }
+ jsize count = env->GetArrayLength(fdsToClose);
+ jint *ar = env->GetIntArrayElements(fdsToClose, 0);
+ if (!ar) {
+ PLOG(FATAL) << "Bad fd array";
+ }
+ jsize i;
+ int devnull;
+ for (i = 0; i < count; i++) {
+ devnull = open("/dev/null", O_RDWR);
+ if (devnull < 0) {
+ PLOG(FATAL) << "Failed to open /dev/null";
+ continue;
+ }
+ PLOG(VERBOSE) << "Switching descriptor " << ar[i] << " to /dev/null";
+ if (dup2(devnull, ar[i]) < 0) {
+ PLOG(FATAL) << "Failed dup2() on descriptor " << ar[i];
+ }
+ close(devnull);
+ }
+}
+
// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
- bool is_system_server) {
+ bool is_system_server, jintArray fdsToClose) {
Runtime* runtime = Runtime::Current();
CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";
if (!runtime->PreZygoteFork()) {
@@ -431,6 +463,9 @@
// The child process.
gMallocLeakZygoteChild = 1;
+ // Clean up any descriptors which must be closed immediately
+ DetachDescriptors(env, fdsToClose);
+
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
EnableKeepCapabilities();
@@ -531,11 +566,19 @@
return pid;
}
+static jint Zygote_nativeForkAndSpecialize_new(JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
+ jint debug_flags, jobjectArray rlimits,
+ jint mount_external, jstring se_info, jstring se_name,
+ jintArray fdsToClose) {
+ return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, 0, 0, mount_external,
+ se_info, se_name, false, fdsToClose);
+}
+
static jint Zygote_nativeForkAndSpecialize(JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name) {
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, 0, 0, mount_external,
- se_info, se_name, false);
+ se_info, se_name, false, NULL);
}
static jint Zygote_nativeForkSystemServer(JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
@@ -545,7 +588,7 @@
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
- MOUNT_EXTERNAL_NONE, NULL, NULL, true);
+ MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
if (pid > 0) {
// The zygote process checks whether the child process has died or not.
LOG(INFO) << "System server process " << pid << " has been created";
@@ -562,6 +605,7 @@
}
static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(Zygote, nativeForkAndSpecialize_new, "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I"),
NATIVE_METHOD(Zygote, nativeForkAndSpecialize, "(II[II[[IILjava/lang/String;Ljava/lang/String;)I"),
NATIVE_METHOD(Zygote, nativeForkSystemServer, "(II[II[[IJJ)I"),
};
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index d8f9ca3..6ca45e8 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -765,12 +765,6 @@
parsed->image_ += GetAndroidRoot();
parsed->image_ += "/framework/boot.art";
}
- if (!kIsTargetBuild && parsed->host_prefix_.empty()) {
- const char* build_top = getenv("ANDROID_BUILD_TOP");
- if (build_top != NULL) {
- parsed->host_prefix_ = build_top;
- }
- }
if (parsed->heap_growth_limit_ == 0) {
parsed->heap_growth_limit_ = parsed->heap_maximum_size_;
}
@@ -840,7 +834,7 @@
bool Runtime::Start() {
VLOG(startup) << "Runtime::Start entering";
- CHECK(!kIsTargetBuild || host_prefix_.empty()) << host_prefix_;
+ CHECK(host_prefix_.empty()) << host_prefix_;
// Restore main thread state to kNative as expected by native code.
Thread* self = Thread::Current();
diff --git a/tools/Android.mk b/tools/Android.mk
deleted file mode 100644
index 6c385dc..0000000
--- a/tools/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-ifeq ($(WITH_HOST_DALVIK),true)
-# Copy the art shell script to the host's bin directory
-include $(CLEAR_VARS)
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE := art
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/art $(ACP)
- @echo "Copy: $(PRIVATE_MODULE) ($@)"
- $(copy-file-to-new-target)
- $(hide) chmod 755 $@
-
-endif
diff --git a/tools/art b/tools/art
index 2e3a46e..0a6c941 100755
--- a/tools/art
+++ b/tools/art
@@ -34,22 +34,8 @@
done
unset ANDROID_PRODUCT_OUT # avoid defaulting dex2oat --host-prefix to target output
-
-function follow_links() {
- file="$1"
- while [ -h "$file" ]; do
- # On Mac OS, readlink -f doesn't work.
- file="$(readlink "$file")"
- done
- echo "$file"
-}
-
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-ANDROID_BUILD_TOP="$(cd "${PROG_DIR}/../../../../" ; pwd -P)/"
-ANDROID_HOST_OUT=$PROG_DIR/..
-
mkdir -p /tmp/android-data/dalvik-cache
+cd $ANDROID_BUILD_TOP
ANDROID_DATA=/tmp/android-data \
ANDROID_ROOT=$ANDROID_HOST_OUT \
LD_LIBRARY_PATH=$ANDROID_HOST_OUT/lib \