Merge "Marquee text RTL improvements"
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index cb7e1a0..7c25354 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -14,30 +14,11 @@
libandroid_runtime
LOCAL_MODULE:= app_process
-LOCAL_32_BIT_ONLY := true
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := app_process
+LOCAL_MODULE_STEM_64 := app_process64
include $(BUILD_EXECUTABLE)
-ifeq ($(TARGET_IS_64_BIT),true)
-
-# 64-bit app_process64
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- app_main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- liblog \
- libbinder \
- libandroid_runtime
-
-LOCAL_MODULE:= app_process64
-LOCAL_NO_2ND_ARCH := true
-include $(BUILD_EXECUTABLE)
-
-endif # TARGET_IS_64_BIT
-
# Build a variant of app_process binary linked with ASan runtime.
# ARM-only at the moment.
ifeq ($(TARGET_ARCH),arm)
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 8d2b739..bdbb08c 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -30,8 +30,9 @@
class AppRuntime : public AndroidRuntime
{
public:
- AppRuntime()
- : mParentDir(NULL)
+ AppRuntime(char* argBlockStart, const size_t argBlockLength)
+ : AndroidRuntime(argBlockStart, argBlockLength)
+ , mParentDir(NULL)
, mClassName(NULL)
, mClass(NULL)
, mArgC(0)
@@ -125,29 +126,30 @@
using namespace android;
-/*
- * sets argv0 to as much of newArgv0 as will fit
- */
-static void setArgv0(const char *argv0, const char *newArgv0)
-{
- strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
+static size_t computeArgBlockSize(int argc, char* const argv[]) {
+ // TODO: This assumes that all arguments are allocated in
+ // contiguous memory. There isn't any documented guarantee
+ // that this is the case, but this is how the kernel does it
+ // (see fs/exec.c).
+ //
+ // Also note that this is a constant for "normal" android apps.
+ // Since they're forked from zygote, the size of their command line
+ // is the size of the zygote command line.
+ //
+ // We change the process name of the process by over-writing
+ // the start of the argument block (argv[0]) with the new name of
+ // the process, so we'd mysteriously start getting truncated process
+ // names if the zygote command line decreases in size.
+ uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]);
+ uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]);
+ end += strlen(argv[argc - 1]);
+
+ return (end - start);
}
int main(int argc, char* const argv[])
{
- // These are global variables in ProcessState.cpp
- mArgC = argc;
- mArgV = argv;
-
- mArgLen = 0;
- for (int i=0; i<argc; i++) {
- mArgLen += strlen(argv[i]) + 1;
- }
- mArgLen--;
-
- AppRuntime runtime;
- const char* argv0 = argv[0];
-
+ AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
@@ -184,7 +186,7 @@
}
if (niceName && *niceName) {
- setArgv0(argv0, niceName);
+ runtime.setArgv0(niceName);
set_process_name(niceName);
}
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index a28b5a7..d06355d 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -22,6 +22,8 @@
import java.io.IOException;
import java.lang.reflect.Method;
import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
@@ -74,13 +76,16 @@
private CertificateChainValidator() {
try {
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509");
+ tmf.init((KeyStore) null);
for (TrustManager tm : tmf.getTrustManagers()) {
if (tm instanceof X509ExtendedTrustManager) {
mTrustManager = (X509ExtendedTrustManager) tm;
}
}
} catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("X.509 TrustManager factory must be available", e);
+ throw new RuntimeException("X.509 TrustManagerFactory must be available", e);
+ } catch (KeyStoreException e) {
+ throw new RuntimeException("X.509 TrustManagerFactory cannot be initialized", e);
}
if (mTrustManager == null) {
@@ -166,9 +171,13 @@
TrustManagerFactory tmf;
try {
tmf = TrustManagerFactory.getInstance("X.509");
+ tmf.init((KeyStore) null);
} catch (NoSuchAlgorithmException e) {
Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory");
return;
+ } catch (KeyStoreException e) {
+ Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e);
+ return;
}
TrustManager[] tms = tmf.getTrustManagers();
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index 666832a..d730a7b 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -56,7 +56,8 @@
if (tm instanceof TrustManagerImpl) {
mDelegate = (TrustManagerImpl) tm;
} else {
- throw new IllegalArgumentException("tm is not a supported type of X509TrustManager");
+ throw new IllegalArgumentException("tm is an instance of " + tm.getClass().getName() +
+ " which is not a supported type of X509TrustManager");
}
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 631edd6..4cf8767 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -16,10 +16,11 @@
package android.os;
-import android.net.LocalSocketAddress;
import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
import android.util.Log;
-import dalvik.system.Zygote;
+
+import com.android.internal.os.Zygote;
import java.io.BufferedWriter;
import java.io.DataInputStream;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index aa43bad..cd905fa 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -591,6 +591,7 @@
Object[] args = mConstructorArgs;
args[1] = attrs;
+ constructor.setAccessible(true);
final View view = constructor.newInstance(args);
if (view instanceof ViewStub) {
// always use ourselves when inflating ViewStub later
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bc0d7e3..3fd2aa9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -660,7 +660,7 @@
mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(MSG_FLUSH_LAYER_UPDATES));
}
- public boolean attachFunctor(int functor) {
+ public boolean attachFunctor(long functor) {
//noinspection SimplifiableIfStatement
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
return mAttachInfo.mHardwareRenderer.attachFunctor(mAttachInfo, functor);
@@ -668,7 +668,7 @@
return false;
}
- public void detachFunctor(int functor) {
+ public void detachFunctor(long functor) {
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.detachFunctor(functor);
}
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index c6b3e7c..3301cbe 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -25,9 +25,6 @@
import java.io.IOException;
import libcore.io.IoUtils;
-import libcore.io.Libcore;
-
-import dalvik.system.Zygote;
/**
* Startup class for the wrapper process.
@@ -95,7 +92,7 @@
* @param niceName The nice name for the application, or null if none.
* @param targetSdkVersion The target SDK version for the app.
* @param pipeFd The pipe to which the application's pid should be written, or null if none.
- * @param args Arguments for {@link RuntimeInit.main}.
+ * @param args Arguments for {@link RuntimeInit#main}.
*/
public static void execApplication(String invokeWith, String niceName,
int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
new file mode 100644
index 0000000..c5fa0a1
--- /dev/null
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -0,0 +1,164 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.os;
+
+
+import dalvik.system.ZygoteHooks;
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+
+/** @hide */
+public final class Zygote {
+ /*
+ * Bit values for "debugFlags" argument. The definitions are duplicated
+ * in the native code.
+ */
+
+ /** enable debugging over JDWP */
+ public static final int DEBUG_ENABLE_DEBUGGER = 1;
+ /** enable JNI checks */
+ public static final int DEBUG_ENABLE_CHECKJNI = 1 << 1;
+ /** enable Java programming language "assert" statements */
+ public static final int DEBUG_ENABLE_ASSERT = 1 << 2;
+ /** disable the JIT compiler */
+ public static final int DEBUG_ENABLE_SAFEMODE = 1 << 3;
+ /** Enable logging of third-party JNI activity. */
+ public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
+
+ /** No external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_NONE = 0;
+ /** Single-user external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_SINGLEUSER = 1;
+ /** Multi-user external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_MULTIUSER = 2;
+ /** All multi-user external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_MULTIUSER_ALL = 3;
+
+ private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
+
+ private Zygote() {}
+
+ /**
+ * Forks a new VM instance. The current VM must have been started
+ * with the -Xzygote flag. <b>NOTE: new instance keeps all
+ * root capabilities. The new process is expected to call capset()</b>.
+ *
+ * @param uid the UNIX uid that the new process should setuid() to after
+ * fork()ing and and before spawning any threads.
+ * @param gid the UNIX gid that the new process should setgid() to after
+ * fork()ing and and before spawning any threads.
+ * @param gids null-ok; a list of UNIX gids that the new process should
+ * setgroups() to after fork and before spawning any threads.
+ * @param debugFlags bit flags that enable debugging features.
+ * @param rlimits null-ok an array of rlimit tuples, with the second
+ * dimension having a length of 3 and representing
+ * (resource, rlim_cur, rlim_max). These are set via the posix
+ * setrlimit(2) call.
+ * @param seInfo null-ok a string specifying SELinux information for
+ * the new process.
+ * @param niceName null-ok a string specifying the process name.
+ * @param fdsToClose an array of ints, holding one or more POSIX
+ * file descriptor numbers that are to be closed by the child
+ * (and replaced by /dev/null) after forking. An integer value
+ * of -1 in any entry in the array means "ignore this one".
+ *
+ * @return 0 if this is the child, pid of the child
+ * if this is the parent, or -1 on error.
+ */
+ public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
+ int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+ VM_HOOKS.preFork();
+ int pid = nativeForkAndSpecialize(
+ uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+ VM_HOOKS.postForkCommon();
+ return pid;
+ }
+
+ native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
+ int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
+
+ /**
+ * Special method to start the system server process. In addition to the
+ * common actions performed in forkAndSpecialize, the pid of the child
+ * process is recorded such that the death of the child process will cause
+ * zygote to exit.
+ *
+ * @param uid the UNIX uid that the new process should setuid() to after
+ * fork()ing and and before spawning any threads.
+ * @param gid the UNIX gid that the new process should setgid() to after
+ * fork()ing and and before spawning any threads.
+ * @param gids null-ok; a list of UNIX gids that the new process should
+ * setgroups() to after fork and before spawning any threads.
+ * @param debugFlags bit flags that enable debugging features.
+ * @param rlimits null-ok an array of rlimit tuples, with the second
+ * dimension having a length of 3 and representing
+ * (resource, rlim_cur, rlim_max). These are set via the posix
+ * setrlimit(2) call.
+ * @param permittedCapabilities argument for setcap()
+ * @param effectiveCapabilities argument for setcap()
+ *
+ * @return 0 if this is the child, pid of the child
+ * if this is the parent, or -1 on error.
+ */
+ public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+ int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
+ VM_HOOKS.preFork();
+ int pid = nativeForkSystemServer(
+ uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
+ VM_HOOKS.postForkCommon();
+ return pid;
+ }
+
+ native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+ int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
+
+ private static void callPostForkChildHooks(int debugFlags) {
+ VM_HOOKS.postForkChild(debugFlags);
+ }
+
+
+ /**
+ * Executes "/system/bin/sh -c <command>" using the exec() system call.
+ * This method throws a runtime exception if exec() failed, otherwise, this
+ * method never returns.
+ *
+ * @param command The shell command to execute.
+ */
+ public static void execShell(String command) {
+ String[] args = { "/system/bin/sh", "-c", command };
+ try {
+ Libcore.os.execv(args[0], args);
+ } catch (ErrnoException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Appends quotes shell arguments to the specified string builder.
+ * The arguments are quoted using single-quotes, escaped if necessary,
+ * prefixed with a space, and appended to the command.
+ *
+ * @param command A string builder for the shell command being constructed.
+ * @param args An array of argument strings to be quoted and appended to the command.
+ * @see #execShell(String)
+ */
+ public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
+ for (String arg : args) {
+ command.append(" '").append(arg.replace("'", "'\\''")).append("'");
+ }
+ }
+}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index f9a1f89..aad534c 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -24,7 +24,6 @@
import android.util.Log;
import dalvik.system.PathClassLoader;
-import dalvik.system.Zygote;
import java.io.BufferedReader;
import java.io.DataInputStream;
@@ -807,7 +806,7 @@
/**
* Applies invoke-with system properties to the zygote arguments.
*
- * @param parsedArgs non-null; zygote args
+ * @param args non-null; zygote args
*/
public static void applyInvokeWithSystemProperty(Arguments args) {
if (args.invokeWith == null && args.niceName != null) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index cc24ff7..5be29b4 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -32,7 +32,6 @@
import android.util.Log;
import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
import libcore.io.IoUtils;
import libcore.io.Libcore;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index ac70738..fda4114 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -149,7 +149,8 @@
android_content_res_ObbScanner.cpp \
android_content_res_Configuration.cpp \
android_animation_PropertyValuesHolder.cpp \
- com_android_internal_net_NetworkStatsFactory.cpp
+ com_android_internal_net_NetworkStatsFactory.cpp \
+ com_android_internal_os_Zygote.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 649968e..cce4e0d 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -177,6 +177,7 @@
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
+extern int register_com_android_internal_os_Zygote(JNIEnv *env);
static AndroidRuntime* gCurRuntime = NULL;
@@ -227,9 +228,10 @@
/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
-
-AndroidRuntime::AndroidRuntime() :
- mExitWithoutCleanup(false)
+AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
+ mExitWithoutCleanup(false),
+ mArgBlockStart(argBlockStart),
+ mArgBlockLength(argBlockLength)
{
SkGraphics::Init();
// this sets our preference for 16bit images during decode
@@ -264,6 +266,10 @@
return jniRegisterNativeMethods(env, className, gMethods, numMethods);
}
+void AndroidRuntime::setArgv0(const char* argv0) {
+ strlcpy(mArgBlockStart, argv0, mArgBlockLength);
+}
+
status_t AndroidRuntime::callMain(const char* className,
jclass clazz, int argc, const char* const argv[])
{
@@ -1241,6 +1247,7 @@
REG_JNI(register_android_net_wifi_WifiNative),
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_android_hardware_Camera),
REG_JNI(register_android_hardware_camera2_CameraMetadata),
REG_JNI(register_android_hardware_SensorManager),
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 92d253f..e2c78b1 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -69,7 +69,7 @@
size_t totalSizeToDelete = text.getSize() + desc->getSize();
mSize -= totalSizeToDelete;
if (mDebugEnabled) {
- ALOGD("Cache value %p deleted, size = %d", desc.get(), totalSizeToDelete);
+ ALOGD("Cache value %p deleted, size = %zu", desc.get(), totalSizeToDelete);
}
}
@@ -129,7 +129,7 @@
bool removedOne = mCache.removeOldest();
LOG_ALWAYS_FATAL_IF(!removedOne, "The cache is non-empty but we "
"failed to remove the oldest entry. "
- "mSize = %u, size = %u, mMaxSize = %u, mCache.size() = %u",
+ "mSize = %u, size = %zu, mMaxSize = %u, mCache.size() = %zu",
mSize, size, mMaxSize, mCache.size());
}
}
@@ -148,7 +148,7 @@
nsecs_t totalTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
ALOGD("CACHE MISS: Added entry %p "
"with start = %d, count = %d, contextCount = %d, "
- "entry size %d bytes, remaining space %d bytes"
+ "entry size %zu bytes, remaining space %d bytes"
" - Compute time %0.6f ms - Put time %0.6f ms - Text = '%s'",
value.get(), start, count, contextCount, size, mMaxSize - mSize,
value->getElapsedTime() * 0.000001f,
@@ -159,7 +159,7 @@
if (mDebugEnabled) {
ALOGD("CACHE MISS: Calculated but not storing entry because it is too big "
"with start = %d, count = %d, contextCount = %d, "
- "entry size %d bytes, remaining space %d bytes"
+ "entry size %zu bytes, remaining space %d bytes"
" - Compute time %0.6f ms - Text = '%s'",
start, count, contextCount, size, mMaxSize - mSize,
value->getElapsedTime() * 0.000001f,
@@ -204,7 +204,7 @@
ALOGD("------------------------------------------------");
ALOGD("pid : %d", getpid());
ALOGD("running : %.0f seconds", timeRunningInSec);
- ALOGD("entries : %d", cacheSize);
+ ALOGD("entries : %zu", cacheSize);
ALOGD("max size : %d bytes", mMaxSize);
ALOGD("used : %d bytes according to mSize", mSize);
ALOGD("remaining : %d bytes or %2.2f percent", mMaxSize - mSize, remainingPercent);
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index 9f79f74..98f4bed 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -111,7 +111,7 @@
/* private native void listen_native(int fd, int backlog) throws IOException; */
static void
-socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, int backlog)
+socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, jint backlog)
{
int ret;
int fd;
@@ -231,7 +231,7 @@
}
static jint
-socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, int optID)
+socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, jint optID)
{
int ret, value;
int opt, level;
@@ -279,7 +279,7 @@
}
static void socket_setOption(
- JNIEnv *env, jobject object, jobject fileDescriptor, int optID,
+ JNIEnv *env, jobject object, jobject fileDescriptor, jint optID,
jint boolValue, jint intValue) {
int ret;
int optname;
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp
index 7cbbe12..59d6e41 100644
--- a/core/jni/android_nio_utils.cpp
+++ b/core/jni/android_nio_utils.cpp
@@ -37,7 +37,7 @@
gNioJNI.getBasePointerID, buffer);
if (pointer != 0L) {
*array = NULL;
- return (void *) (jint) pointer;
+ return reinterpret_cast<void *>(pointer);
}
*array = (jarray) _env->CallStaticObjectMethod(gNioJNI.nioAccessClass,
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index a041693..d4873d6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -800,7 +800,7 @@
fprintf(fp, "Total memory: %zu\n", totalMemory);
fprintf(fp, "Allocation records: %zd\n", recordCount);
if (backtraceSize != BACKTRACE_SIZE) {
- fprintf(fp, "WARNING: mismatched backtrace sizes (%d vs. %d)\n",
+ fprintf(fp, "WARNING: mismatched backtrace sizes (%zu vs. %d)\n",
backtraceSize, BACKTRACE_SIZE);
}
fprintf(fp, "\n");
@@ -823,7 +823,11 @@
if (backtrace[bt] == 0) {
break;
} else {
+#ifdef __LP64__
+ fprintf(fp, " %016x", backtrace[bt]);
+#else
fprintf(fp, " %08x", backtrace[bt]);
+#endif
}
}
fprintf(fp, "\n");
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
index 12beff7..7e12b1e 100644
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ b/core/jni/android_server_NetworkManagementSocketTagger.cpp
@@ -47,8 +47,8 @@
return (jint)res;
}
-static int QTagUid_untagSocketFd(JNIEnv* env, jclass,
- jobject fileDescriptor) {
+static jint QTagUid_untagSocketFd(JNIEnv* env, jclass,
+ jobject fileDescriptor) {
int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
if (env->ExceptionOccurred() != NULL) {
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index d50a69f..6f7ee49 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -26,7 +26,7 @@
namespace android {
static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
- jbyteArray infoArray, int n, jboolean haveInfo)
+ jbyteArray infoArray, jint n, jboolean haveInfo)
{
// Parameters are checked on java side
// Failures from GetXXXArrayElements indicate a serious out-of-memory condition
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 8b85a7b7..94bd40f 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -51,7 +51,8 @@
namespace android {
-static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, jbyteArray destArray, int count)
+static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
+ jbyteArray destArray, jint count)
{
ScopedCharArrayRO src(env, srcArray);
if (src.get() == NULL) {
@@ -102,7 +103,7 @@
}
static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
- int start, int count, jbyteArray destArray)
+ jint start, jint count, jbyteArray destArray)
{
ScopedCharArrayRO src(env, srcArray);
if (src.get() == NULL) {
@@ -144,20 +145,20 @@
}
}
-static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, int start, int count)
+static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, jint start, jint count)
{
ScopedCharArrayRW data(env, charArray);
if (data.get() == NULL) {
- return false;
+ return JNI_FALSE;
}
if (start < 0 || start > start + count
|| env->GetArrayLength(charArray) < start + count) {
jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
- return false;
+ return JNI_FALSE;
}
- bool ret = false;
+ jboolean ret = JNI_FALSE;
for (int i = start; i < start + count; i++) {
// XXX this thinks it knows that surrogates are never mirrored
@@ -166,7 +167,7 @@
if (c1 != c2) {
data[i] = c2;
- ret = true;
+ ret = JNI_TRUE;
}
}
return ret;
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index aa2c5f39..28a8a5d 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -117,7 +117,7 @@
time2java(env, This, t);
RELEASE_TIMEZONE(This, t)
- return result;
+ return static_cast<jlong>(result);
}
static void android_text_format_Time_switchTimezone(JNIEnv* env, jobject This,
@@ -155,7 +155,7 @@
RELEASE_TIMEZONE(aObject, a)
RELEASE_TIMEZONE(bObject, b)
- return result;
+ return static_cast<jint>(result);
}
static jstring android_text_format_Time_format2445(JNIEnv* env, jobject This)
@@ -346,7 +346,7 @@
RELEASE_TIMEZONE(This, t)
- return result;
+ return static_cast<jlong>(result);
}
static void android_text_format_Time_set(JNIEnv* env, jobject This, jlong millis)
@@ -400,10 +400,10 @@
if (len < 8) {
jniThrowException(env, "android/util/TimeFormatException",
"String too short -- expected at least 8 characters.");
- return false;
+ return JNI_FALSE;
}
- jboolean inUtc = false;
+ jboolean inUtc = JNI_FALSE;
ScopedStringChars s(env, strObj);
@@ -414,49 +414,49 @@
n += get_char(env, s, 1, 100, &thrown);
n += get_char(env, s, 2, 10, &thrown);
n += get_char(env, s, 3, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_yearField, n);
// month
n = get_char(env, s, 4, 10, &thrown);
n += get_char(env, s, 5, 1, &thrown);
n--;
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_monField, n);
// day of month
n = get_char(env, s, 6, 10, &thrown);
n += get_char(env, s, 7, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_mdayField, n);
if (len > 8) {
// T
- if (!check_char(env, s, 8, 'T')) return false;
+ if (!check_char(env, s, 8, 'T')) return JNI_FALSE;
env->SetBooleanField(This, g_allDayField, JNI_FALSE);
// hour
n = get_char(env, s, 9, 10, &thrown);
n += get_char(env, s, 10, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_hourField, n);
// min
n = get_char(env, s, 11, 10, &thrown);
n += get_char(env, s, 12, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_minField, n);
// sec
n = get_char(env, s, 13, 10, &thrown);
n += get_char(env, s, 14, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_secField, n);
if (len > 15) {
// Z
- if (!check_char(env, s, 15, 'Z')) return false;
- inUtc = true;
+ if (!check_char(env, s, 15, 'Z')) return JNI_FALSE;
+ inUtc = JNI_TRUE;
}
} else {
env->SetBooleanField(This, g_allDayField, JNI_TRUE);
@@ -481,10 +481,10 @@
if (len < 10) {
jniThrowException(env, "android/util/TimeFormatException",
"String too short --- expected at least 10 characters.");
- return false;
+ return JNI_FALSE;
}
- jboolean inUtc = false;
+ jboolean inUtc = JNI_FALSE;
ScopedStringChars s(env, strObj);
@@ -495,57 +495,57 @@
n += get_char(env, s, 1, 100, &thrown);
n += get_char(env, s, 2, 10, &thrown);
n += get_char(env, s, 3, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_yearField, n);
// -
- if (!check_char(env, s, 4, '-')) return false;
+ if (!check_char(env, s, 4, '-')) return JNI_FALSE;
// month
n = get_char(env, s, 5, 10, &thrown);
n += get_char(env, s, 6, 1, &thrown);
--n;
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_monField, n);
// -
- if (!check_char(env, s, 7, '-')) return false;
+ if (!check_char(env, s, 7, '-')) return JNI_FALSE;
// day
n = get_char(env, s, 8, 10, &thrown);
n += get_char(env, s, 9, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_mdayField, n);
if (len >= 19) {
// T
- if (!check_char(env, s, 10, 'T')) return false;
+ if (!check_char(env, s, 10, 'T')) return JNI_FALSE;
env->SetBooleanField(This, g_allDayField, JNI_FALSE);
// hour
n = get_char(env, s, 11, 10, &thrown);
n += get_char(env, s, 12, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
int hour = n;
// env->SetIntField(This, g_hourField, n);
// :
- if (!check_char(env, s, 13, ':')) return false;
+ if (!check_char(env, s, 13, ':')) return JNI_FALSE;
// minute
n = get_char(env, s, 14, 10, &thrown);
n += get_char(env, s, 15, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
int minute = n;
// env->SetIntField(This, g_minField, n);
// :
- if (!check_char(env, s, 16, ':')) return false;
+ if (!check_char(env, s, 16, ':')) return JNI_FALSE;
// second
n = get_char(env, s, 17, 10, &thrown);
n += get_char(env, s, 18, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_secField, n);
// skip the '.XYZ' -- we don't care about subsecond precision.
@@ -579,32 +579,32 @@
jniThrowExceptionFmt(env, "android/util/TimeFormatException",
"Unexpected character 0x%02x at position %d. Expected + or -",
c, tz_index);
- return false;
+ return JNI_FALSE;
}
- inUtc = true;
+ inUtc = JNI_TRUE;
if (offset != 0) {
if (len < tz_index + 6) {
jniThrowExceptionFmt(env, "android/util/TimeFormatException",
"Unexpected length; should be %d characters",
tz_index + 6);
- return false;
+ return JNI_FALSE;
}
// hour
n = get_char(env, s, tz_index + 1, 10, &thrown);
n += get_char(env, s, tz_index + 2, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
n *= offset;
hour += n;
// :
- if (!check_char(env, s, tz_index + 3, ':')) return false;
+ if (!check_char(env, s, tz_index + 3, ':')) return JNI_FALSE;
// minute
n = get_char(env, s, tz_index + 4, 10, &thrown);
n += get_char(env, s, tz_index + 5, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
n *= offset;
minute += n;
}
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 536a582..93dcbef 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -85,7 +85,7 @@
jboolean result = false;
if ((strlen(chars)+sizeof(LOG_NAMESPACE)) > PROPERTY_KEY_MAX) {
char buf2[200];
- snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %d characters\n",
+ snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %zu characters\n",
chars, PROPERTY_KEY_MAX - sizeof(LOG_NAMESPACE));
jniThrowException(env, "java/lang/IllegalArgumentException", buf2);
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 601975a..9f8eb34 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -19,8 +19,8 @@
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <cutils/process_name.h>
#include <cutils/sched_policy.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -402,7 +402,9 @@
}
if (name8.size() > 0) {
- ProcessState::self()->setArgV0(name8.string());
+ const char* procName = name8.string();
+ set_process_name(procName);
+ AndroidRuntime::getRuntime()->setArgv0(procName);
}
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
new file mode 100644
index 0000000..a61fa87
--- /dev/null
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -0,0 +1,608 @@
+/*
+ * 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.
+ */
+
+#include "android_runtime/AndroidRuntime.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 <grp.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/resource.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"
+#include "cutils/sched_policy.h"
+#include "utils/String8.h"
+#include "JNIHelp.h"
+#include "ScopedLocalRef.h"
+#include "ScopedPrimitiveArray.h"
+#include "ScopedUtfChars.h"
+
+#if defined(HAVE_PRCTL)
+#include <sys/prctl.h>
+#endif
+
+#include <selinux/android.h>
+
+#if defined(__linux__)
+#include <sys/personality.h>
+#include <sys/utsname.h>
+#if defined(HAVE_ANDROID_OS)
+#include <sys/capability.h>
+#endif
+#endif
+
+namespace {
+
+using android::String8;
+
+static pid_t gSystemServerPid = 0;
+
+static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
+static jclass gZygoteClass;
+static jmethodID gCallPostForkChildHooks;
+
+// Must match values in com.android.internal.os.Zygote.
+enum MountExternalKind {
+ MOUNT_EXTERNAL_NONE = 0,
+ MOUNT_EXTERNAL_SINGLEUSER = 1,
+ MOUNT_EXTERNAL_MULTIUSER = 2,
+ MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
+};
+
+static void RuntimeAbort(JNIEnv* env) {
+ env->FatalError("RuntimeAbort");
+}
+
+// This signal handler is for zygote mode, since the zygote must reap its children
+static void SigChldHandler(int /*signal_number*/) {
+ pid_t pid;
+ int status;
+
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ // Log process-death status that we care about. In general it is
+ // not safe to call LOG(...) from a signal handler because of
+ // possible reentrancy. However, we know a priori that the
+ // current implementation of LOG() is safe to call from a SIGCHLD
+ // handler in the zygote process. If the LOG() implementation
+ // changes its locking strategy or its use of syscalls within the
+ // lazy-init critical section, its use here may become unsafe.
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status)) {
+ ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+ } else if (false) {
+ ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+ }
+ } else if (WIFSIGNALED(status)) {
+ if (WTERMSIG(status) != SIGKILL) {
+ ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+ } else if (false) {
+ ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+ }
+#ifdef WCOREDUMP
+ if (WCOREDUMP(status)) {
+ ALOGI("Process %d dumped core.", pid);
+ }
+#endif /* ifdef WCOREDUMP */
+ }
+
+ // If the just-crashed process is the system_server, bring down zygote
+ // so that it is restarted by init and system server will be restarted
+ // from there.
+ if (pid == gSystemServerPid) {
+ ALOGE("Exit zygote because system server (%d) has terminated");
+ kill(getpid(), SIGKILL);
+ }
+ }
+
+ if (pid < 0) {
+ ALOGW("Zygote SIGCHLD error in waitpid: %d", errno);
+ }
+}
+
+// Configures the SIGCHLD handler for the zygote process. This is configured
+// very late, because earlier in the runtime we may fork() and exec()
+// other processes, and we want to waitpid() for those rather than
+// have them be harvested immediately.
+//
+// This ends up being called repeatedly before each fork(), but there's
+// no real harm in that.
+static void SetSigChldHandler() {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SigChldHandler;
+
+ int err = sigaction(SIGCHLD, &sa, NULL);
+ if (err < 0) {
+ ALOGW("Error setting SIGCHLD handler: %d", errno);
+ }
+}
+
+// Sets the SIGCHLD handler back to default behavior in zygote children.
+static void UnsetSigChldHandler() {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+
+ int err = sigaction(SIGCHLD, &sa, NULL);
+ if (err < 0) {
+ ALOGW("Error unsetting SIGCHLD handler: %d", errno);
+ }
+}
+
+// Calls POSIX setgroups() using the int[] object as an argument.
+// A NULL argument is tolerated.
+static void SetGids(JNIEnv* env, jintArray javaGids) {
+ if (javaGids == NULL) {
+ return;
+ }
+
+ ScopedIntArrayRO gids(env, javaGids);
+ if (gids.get() == NULL) {
+ RuntimeAbort(env);
+ }
+ int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
+ if (rc == -1) {
+ ALOGE("setgroups failed");
+ RuntimeAbort(env);
+ }
+}
+
+// Sets the resource limits via setrlimit(2) for the values in the
+// two-dimensional array of integers that's passed in. The second dimension
+// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
+// treated as an empty array.
+static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
+ if (javaRlimits == NULL) {
+ return;
+ }
+
+ rlimit rlim;
+ memset(&rlim, 0, sizeof(rlim));
+
+ for (int i = 0; i < env->GetArrayLength(javaRlimits); ++i) {
+ ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
+ ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
+ if (javaRlimit.size() != 3) {
+ ALOGE("rlimits array must have a second dimension of size 3");
+ RuntimeAbort(env);
+ }
+
+ rlim.rlim_cur = javaRlimit[1];
+ rlim.rlim_max = javaRlimit[2];
+
+ int rc = setrlimit(javaRlimit[0], &rlim);
+ if (rc == -1) {
+ ALOGE("setrlimit(%d, {%d, %d}) failed", javaRlimit[0], rlim.rlim_cur, rlim.rlim_max);
+ RuntimeAbort(env);
+ }
+ }
+}
+
+#if defined(HAVE_ANDROID_OS)
+
+// The debug malloc library needs to know whether it's the zygote or a child.
+extern "C" int gMallocLeakZygoteChild;
+
+static void EnableKeepCapabilities(JNIEnv* env) {
+ int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+ if (rc == -1) {
+ ALOGE("prctl(PR_SET_KEEPCAPS) failed");
+ RuntimeAbort(env);
+ }
+}
+
+static void DropCapabilitiesBoundingSet(JNIEnv* env) {
+ for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+ int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+ if (rc == -1) {
+ if (errno == EINVAL) {
+ ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
+ "your kernel is compiled with file capabilities support");
+ } else {
+ ALOGE("prctl(PR_CAPBSET_DROP) failed");
+ RuntimeAbort(env);
+ }
+ }
+ }
+}
+
+static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
+ __user_cap_header_struct capheader;
+ memset(&capheader, 0, sizeof(capheader));
+ capheader.version = _LINUX_CAPABILITY_VERSION_3;
+ capheader.pid = 0;
+
+ __user_cap_data_struct capdata[2];
+ memset(&capdata, 0, sizeof(capdata));
+ capdata[0].effective = effective;
+ capdata[1].effective = effective >> 32;
+ capdata[0].permitted = permitted;
+ capdata[1].permitted = permitted >> 32;
+
+ if (capset(&capheader, &capdata[0]) == -1) {
+ ALOGE("capset(%lld, %lld) failed", permitted, effective);
+ RuntimeAbort(env);
+ }
+}
+
+static void SetSchedulerPolicy(JNIEnv* env) {
+ errno = -set_sched_policy(0, SP_DEFAULT);
+ if (errno != 0) {
+ ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
+ RuntimeAbort(env);
+ }
+}
+
+#else
+
+static int gMallocLeakZygoteChild = 0;
+
+static void EnableKeepCapabilities(JNIEnv*) {}
+static void DropCapabilitiesBoundingSet(JNIEnv*) {}
+static void SetCapabilities(JNIEnv*, int64_t, int64_t) {}
+static void SetSchedulerPolicy(JNIEnv*) {}
+
+#endif
+
+// 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;
+ }
+
+ // See storage config details at http://source.android.com/tech/storage/
+ userid_t user_id = multiuser_get_user_id(uid);
+
+ // Create a second private mount namespace for our process
+ if (unshare(CLONE_NEWNS) == -1) {
+ ALOGW("Failed to unshare(): %d", errno);
+ return false;
+ }
+
+ // 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) {
+ ALOGW("Storage environment undefined; unable to provide external storage");
+ return false;
+ }
+
+ // Prepare source paths
+
+ // /mnt/shell/emulated/0
+ const String8 source_user(String8::format("%s/%d", source, user_id));
+ // /storage/emulated/0
+ const String8 target_user(String8::format("%s/%d", target, user_id));
+
+ if (fs_prepare_dir(source_user.string(), 0000, 0, 0) == -1
+ || fs_prepare_dir(target_user.string(), 0000, 0, 0) == -1) {
+ return false;
+ }
+
+ if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+ // Mount entire external storage tree for all users
+ if (TEMP_FAILURE_RETRY(mount(source, target, NULL, MS_BIND, NULL)) == -1) {
+ ALOGW("Failed to mount %s to %s :%d", source, target, errno);
+ return false;
+ }
+ } else {
+ // Only mount user-specific external storage
+ if (TEMP_FAILURE_RETRY(
+ mount(source_user.string(), target_user.string(), NULL, MS_BIND, NULL)) == -1) {
+ ALOGW("Failed to mount %s to %s: %d", source_user.string(), target_user.string(), errno);
+ return false;
+ }
+ }
+
+ if (fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
+ return false;
+ }
+
+ // Finally, mount user-specific path into place for legacy users
+ if (TEMP_FAILURE_RETRY(
+ mount(target_user.string(), legacy, NULL, MS_BIND | MS_REC, NULL)) == -1) {
+ ALOGW("Failed to mount %s to %s: %d", target_user.string(), legacy, errno);
+ return false;
+ }
+ } else {
+ ALOGW("Mount mode %d unsupported", mount_mode);
+ return false;
+ }
+
+ return true;
+}
+
+#if defined(__linux__)
+static bool NeedsNoRandomizeWorkaround() {
+#if !defined(__arm__)
+ return false;
+#else
+ int major;
+ int minor;
+ struct utsname uts;
+ if (uname(&uts) == -1) {
+ return false;
+ }
+
+ if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+ return false;
+ }
+
+ // Kernels before 3.4.* need the workaround.
+ return (major < 3) || ((major == 3) && (minor < 4));
+#endif
+}
+#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) {
+ ALOGE("Bad fd array");
+ RuntimeAbort(env);
+ }
+ jsize i;
+ int devnull;
+ for (i = 0; i < count; i++) {
+ devnull = open("/dev/null", O_RDWR);
+ if (devnull < 0) {
+ ALOGE("Failed to open /dev/null");
+ RuntimeAbort(env);
+ continue;
+ }
+ ALOGV("Switching descriptor %d to /dev/null: %d", ar[i], errno);
+ if (dup2(devnull, ar[i]) < 0) {
+ ALOGE("Failed dup2() on descriptor %d", ar[i]);
+ RuntimeAbort(env);
+ }
+ close(devnull);
+ }
+}
+
+void SetThreadName(const char* thread_name) {
+ bool hasAt = false;
+ bool hasDot = false;
+ const char* s = thread_name;
+ while (*s) {
+ if (*s == '.') {
+ hasDot = true;
+ } else if (*s == '@') {
+ hasAt = true;
+ }
+ s++;
+ }
+ const int len = s - thread_name;
+ if (len < 15 || hasAt || !hasDot) {
+ s = thread_name;
+ } else {
+ s = thread_name + len - 15;
+ }
+ // pthread_setname_np fails rather than truncating long strings.
+ char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded into bionic
+ strlcpy(buf, s, sizeof(buf)-1);
+ errno = pthread_setname_np(pthread_self(), buf);
+ if (errno != 0) {
+ ALOGW("Unable to set the name of current thread to '%s'", buf);
+ }
+}
+
+// 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, jintArray fdsToClose) {
+ SetSigChldHandler();
+
+ pid_t pid = fork();
+
+ if (pid == 0) {
+ // 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(env);
+ }
+
+ DropCapabilitiesBoundingSet(env);
+
+ if (!MountEmulatedStorage(uid, mount_external)) {
+ ALOGW("Failed to mount emulated storage: %d", errno);
+ 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 {
+ ALOGE("Cannot continue without emulated storage");
+ RuntimeAbort(env);
+ }
+ }
+
+ SetGids(env, javaGids);
+
+ SetRLimits(env, javaRlimits);
+
+ int rc = setresgid(gid, gid, gid);
+ if (rc == -1) {
+ ALOGE("setresgid(%d) failed", gid);
+ RuntimeAbort(env);
+ }
+
+ rc = setresuid(uid, uid, uid);
+ if (rc == -1) {
+ ALOGE("setresuid(%d) failed", uid);
+ RuntimeAbort(env);
+ }
+
+#if defined(__linux__)
+ if (NeedsNoRandomizeWorkaround()) {
+ // Work around ARM kernel ASLR lossage (http://b/5817320).
+ int old_personality = personality(0xffffffff);
+ int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
+ if (new_personality == -1) {
+ ALOGW("personality(%d) failed", new_personality);
+ }
+ }
+#endif
+
+ SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
+
+ SetSchedulerPolicy(env);
+
+#if defined(HAVE_ANDROID_OS)
+ { // NOLINT(whitespace/braces)
+ const char* se_info_c_str = NULL;
+ ScopedUtfChars* se_info = NULL;
+ if (java_se_info != NULL) {
+ se_info = new ScopedUtfChars(env, java_se_info);
+ se_info_c_str = se_info->c_str();
+ if (se_info_c_str == NULL) {
+ ALOGE("se_info_c_str == NULL");
+ RuntimeAbort(env);
+ }
+ }
+ const char* se_name_c_str = NULL;
+ ScopedUtfChars* se_name = NULL;
+ if (java_se_name != NULL) {
+ se_name = new ScopedUtfChars(env, java_se_name);
+ se_name_c_str = se_name->c_str();
+ if (se_name_c_str == NULL) {
+ ALOGE("se_name_c_str == NULL");
+ RuntimeAbort(env);
+ }
+ }
+ rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
+ if (rc == -1) {
+ ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+ is_system_server, se_info_c_str, se_name_c_str);
+ RuntimeAbort(env);
+ }
+
+ // Make it easier to debug audit logs by setting the main thread's name to the
+ // nice name rather than "app_process".
+ if (se_info_c_str == NULL && is_system_server) {
+ se_name_c_str = "system_server";
+ }
+ if (se_info_c_str != NULL) {
+ SetThreadName(se_name_c_str);
+ }
+
+ delete se_info;
+ delete se_name;
+ }
+#else
+ UNUSED(is_system_server);
+ UNUSED(java_se_info);
+ UNUSED(java_se_name);
+#endif
+
+ UnsetSigChldHandler();
+
+ env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+ if (env->ExceptionCheck()) {
+ ALOGE("Error calling post fork hooks.");
+ RuntimeAbort(env);
+ }
+ } else if (pid > 0) {
+ // the parent process
+ }
+ return pid;
+}
+} // anonymous namespace
+
+namespace android {
+
+static jint com_android_internal_os_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,
+ jintArray fdsToClose) {
+ return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
+ rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose);
+}
+
+static jint com_android_internal_os_Zygote_nativeForkSystemServer(
+ JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
+ jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
+ jlong effectiveCapabilities) {
+ pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
+ debug_flags, rlimits,
+ permittedCapabilities, effectiveCapabilities,
+ MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
+ if (pid > 0) {
+ // The zygote process checks whether the child process has died or not.
+ ALOGI("System server process %d has been created", pid);
+ gSystemServerPid = pid;
+ // There is a slight window that the system server process has crashed
+ // but it went unnoticed because we haven't published its pid yet. So
+ // we recheck here just to make sure that all is well.
+ int status;
+ if (waitpid(pid, &status, WNOHANG) == pid) {
+ ALOGE("System server process %d has died. Restarting Zygote!", pid);
+ RuntimeAbort(env);
+ }
+ }
+ return pid;
+}
+
+static JNINativeMethod gMethods[] = {
+ { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I",
+ (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
+ { "nativeForkSystemServer", "(II[II[[IJJ)I",
+ (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
+};
+
+int register_com_android_internal_os_Zygote(JNIEnv* env) {
+ gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName));
+ if (gZygoteClass == NULL) {
+ RuntimeAbort(env);
+ }
+ gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V");
+
+ return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
+ gMethods, NELEM(gMethods));
+}
+} // namespace android
+
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 649f4c3..6f2af90 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -34,7 +34,7 @@
class AndroidRuntime
{
public:
- AndroidRuntime();
+ AndroidRuntime(char* argBlockStart, size_t argBlockSize);
virtual ~AndroidRuntime();
enum StartMode {
@@ -44,6 +44,8 @@
Tool,
};
+ void setArgv0(const char* argv0);
+
/**
* Register a set of methods in the specified class.
*/
@@ -120,6 +122,8 @@
Vector<JavaVMOption> mOptions;
bool mExitWithoutCleanup;
+ char* const mArgBlockStart;
+ const size_t mArgBlockLength;
/* JNI JavaVM pointer */
static JavaVM* mJavaVM;
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index 2d0f755..bd9dc76 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -78,7 +78,7 @@
paddingSize = padding_extra(n);
if (paddingSize > 0) {
uint32_t padding = 0xbcbcbcbc;
- if (DEBUG) ALOGI("writing %d padding bytes for %d", paddingSize, n);
+ if (DEBUG) ALOGI("writing %zd padding bytes for %d", paddingSize, n);
amt = write(m_fd, &padding, paddingSize);
if (amt != paddingSize) {
m_status = errno;
@@ -112,7 +112,7 @@
k = key;
}
if (DEBUG) {
- ALOGD("Writing header: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(),
+ ALOGD("Writing header: prefix='%s' key='%s' dataSize=%zu", m_keyPrefix.string(),
key.string(), dataSize);
}
@@ -125,7 +125,7 @@
header.keyLen = tolel(keyLen);
header.dataSize = tolel(dataSize);
- if (DEBUG) ALOGI("writing entity header, %d bytes", sizeof(entity_header_v1));
+ if (DEBUG) ALOGI("writing entity header, %zu bytes", sizeof(entity_header_v1));
amt = write(m_fd, &header, sizeof(entity_header_v1));
if (amt != sizeof(entity_header_v1)) {
m_status = errno;
@@ -133,7 +133,7 @@
}
m_pos += amt;
- if (DEBUG) ALOGI("writing entity header key, %d bytes", keyLen+1);
+ if (DEBUG) ALOGI("writing entity header key, %zd bytes", keyLen+1);
amt = write(m_fd, k.string(), keyLen+1);
if (amt != keyLen+1) {
m_status = errno;
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index ab837ad..52dce9f 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -639,7 +639,7 @@
// size header -- calc len in digits by actually rendering the number
// to a string - brute force but simple
- snprintf(sizeStr, sizeof(sizeStr), "%lld", s.st_size);
+ snprintf(sizeStr, sizeof(sizeStr), "%lld", (long long)s.st_size);
p += write_pax_header_entry(p, "size", sizeStr);
// fullname was generated above with the ustar paths
@@ -661,7 +661,7 @@
// [ 124 : 12 ] size of pax extended header data
memset(paxHeader + 124, 0, 12);
- snprintf(paxHeader + 124, 12, "%011o", p - paxData);
+ snprintf(paxHeader + 124, 12, "%011o", (unsigned int)(p - paxData));
// Checksum and write the pax block header
calc_tar_checksum(paxHeader);
@@ -681,7 +681,10 @@
if (!isdir) {
off64_t toWrite = s.st_size;
while (toWrite > 0) {
- size_t toRead = (toWrite < BUFSIZE) ? toWrite : BUFSIZE;
+ size_t toRead = toWrite;
+ if (toRead > BUFSIZE) {
+ toRead = BUFSIZE;
+ }
ssize_t nRead = read(fd, buf, toRead);
if (nRead < 0) {
err = errno;
@@ -1095,8 +1098,8 @@
if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
|| states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
|| states[i].size != state.size || states[i].crc32 != states[i].crc32) {
- fprintf(stderr, "state %zu expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
- " actual={%d/%d, 0x%08x, %04o, 0x%08x, %3zu} '%s'\n", i,
+ fprintf(stderr, "state %zu expected={%d/%d, %04o, 0x%08x, 0x%08x, %3zu} '%s'\n"
+ " actual={%d/%d, %04o, 0x%08x, 0x%08x, %3d} '%s'\n", i,
states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
states[i].crc32, name.length(), filenames[i].string(),
state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
@@ -1194,7 +1197,7 @@
test_read_header_and_entity(BackupDataReader& reader, const char* str)
{
int err;
- int bufSize = strlen(str)+1;
+ size_t bufSize = strlen(str)+1;
char* buf = (char*)malloc(bufSize);
String8 string;
int cookie = 0x11111111;
@@ -1229,9 +1232,9 @@
err = EINVAL;
goto finished;
}
- if ((int)actualSize != bufSize) {
- fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08zx\n", bufSize,
- actualSize);
+ if (actualSize != bufSize) {
+ fprintf(stderr, "ReadEntityHeader expected dataSize %zu got %zu\n",
+ bufSize, actualSize);
err = EINVAL;
goto finished;
}
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 2b74a33..166863c 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -210,8 +210,8 @@
uint32_t offset = mHeader->freeOffset + padding;
uint32_t nextFreeOffset = offset + size;
if (nextFreeOffset > mSize) {
- ALOGW("Window is full: requested allocation %d bytes, "
- "free space %d bytes, window size %d bytes",
+ ALOGW("Window is full: requested allocation %zu bytes, "
+ "free space %zu bytes, window size %zu bytes",
size, freeSpace(), mSize);
return 0;
}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 652cd4a..1ffe665 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -5996,12 +5996,12 @@
uintptr_t esize = dtohs(ent->size);
if ((esize&0x3) != 0) {
- printf("NON-INTEGER ResTable_entry SIZE: 0x%x\n", esize);
+ printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize);
continue;
}
if ((thisOffset+esize) > typeSize) {
- printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+0x%x (size is 0x%x)\n",
- entriesStart, thisOffset, esize, typeSize);
+ printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+%p (size is 0x%x)\n",
+ entriesStart, thisOffset, (void *)esize, typeSize);
continue;
}
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index b2148b0..442e9ba 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -36,6 +36,7 @@
}
Patch::~Patch() {
+ delete[] vertices;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 8a44604..2f2debc 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -119,6 +119,17 @@
void PatchCache::removeDeferred(Res_png_9patch* patch) {
Mutex::Autolock _l(mLock);
+
+ // Assert that patch is not already garbage
+ size_t count = mGarbage.size();
+ for (size_t i = 0; i < count; i++) {
+ if (patch == mGarbage[i]) {
+ patch = NULL;
+ break;
+ }
+ }
+ LOG_ALWAYS_FATAL_IF(patch == NULL);
+
mGarbage.push(patch);
}
@@ -143,8 +154,8 @@
for (size_t i = 0; i < patchesToRemove.size(); i++) {
const patch_pair_t& pair = patchesToRemove[i];
- // Add a new free block to the list
- const Patch* patch = pair.getSecond();
+ // Release the patch and mark the space in the free list
+ Patch* patch = pair.getSecond();
BufferBlock* block = new BufferBlock(patch->offset, patch->getSize());
block->next = mFreeBlocks;
mFreeBlocks = block;
@@ -152,6 +163,7 @@
mSize -= patch->getSize();
mCache.remove(*pair.getFirst());
+ delete patch;
}
#if DEBUG_PATCHES
@@ -216,6 +228,7 @@
} else {
mFreeBlocks = block->next;
}
+ delete block;
} else {
// Resize the block now that it's occupied
block->offset += size;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index d276a29..77292bf 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -31,9 +31,9 @@
ALOGD("ResourceCache: cacheReport:");
for (size_t i = 0; i < mCache->size(); ++i) {
ResourceReference* ref = mCache->valueAt(i);
- ALOGD(" ResourceCache: mCache(%d): resource, ref = 0x%p, 0x%p",
+ ALOGD(" ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p",
i, mCache->keyAt(i), mCache->valueAt(i));
- ALOGD(" ResourceCache: mCache(%d): refCount, recycled, destroyed, type = %d, %d, %d, %d",
+ ALOGD(" ResourceCache: mCache(%zu): refCount, recycled, destroyed, type = %d, %d, %d, %d",
i, ref->refCount, ref->recycled, ref->destroyed, ref->resourceType);
}
}
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index cc6d0cd..5bdb18a 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -108,7 +108,7 @@
* Returns the current clip in local coordinates. The clip rect is
* transformed by the inverse transform matrix.
*/
- const Rect& getLocalClip();
+ ANDROID_API const Rect& getLocalClip();
/**
* Resets the clip to the specified rect.
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
index 06b477f..57c0320 100644
--- a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
+++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
@@ -32,7 +32,7 @@
struct usb_device *sDevice = NULL;
static void* read_thread(void* arg) {
- int endpoint = (int)arg;
+ int endpoint = (int)(uintptr_t)arg;
int ret = 0;
while (sDevice && ret >= 0) {
@@ -52,7 +52,7 @@
}
static void* write_thread(void* arg) {
- int endpoint = (int)arg;
+ int endpoint = (int)(uintptr_t)arg;
int ret = 0;
while (ret >= 0) {
@@ -136,11 +136,11 @@
}
if ((ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
- pthread_create(&th, NULL, read_thread, (void *)ep1->bEndpointAddress);
- pthread_create(&th, NULL, write_thread, (void *)ep2->bEndpointAddress);
+ pthread_create(&th, NULL, read_thread, (void *)(uintptr_t)ep1->bEndpointAddress);
+ pthread_create(&th, NULL, write_thread, (void *)(uintptr_t)ep2->bEndpointAddress);
} else {
- pthread_create(&th, NULL, read_thread, (void *)ep2->bEndpointAddress);
- pthread_create(&th, NULL, write_thread, (void *)ep1->bEndpointAddress);
+ pthread_create(&th, NULL, read_thread, (void *)(uintptr_t)ep2->bEndpointAddress);
+ pthread_create(&th, NULL, write_thread, (void *)(uintptr_t)ep1->bEndpointAddress);
}
} else {
printf("Found possible android device - attempting to switch to accessory mode\n");
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 543cb6c..854ee79 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -84,7 +84,7 @@
jbyteArray byteArrayObj = env->NewByteArray(size);
env->DeleteLocalRef(env->GetObjectClass(mDataSource));
env->DeleteLocalRef(env->GetObjectClass(byteArrayObj));
- ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, size);
+ ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, (jint)size);
env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
env->DeleteLocalRef(byteArrayObj);
if (env->ExceptionCheck()) {
@@ -627,7 +627,7 @@
env->CallVoidMethod(
cryptoInfoObj,
gFields.cryptoInfoSetID,
- numSubSamples,
+ (jint)numSubSamples,
numBytesOfPlainDataObj,
numBytesOfEncryptedDataObj,
keyObj,
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 72ce3cc..8129c0d 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -17,11 +17,12 @@
#define LOG_TAG "MtpDatabaseJNI"
#include "utils/Log.h"
-#include <stdio.h>
#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
#include "jni.h"
#include "JNIHelp.h"
@@ -388,7 +389,7 @@
// release date is stored internally as just the year
if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
char date[20];
- snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
+ snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue);
packet.putString(date);
goto out;
}
@@ -645,7 +646,7 @@
return result;
}
-MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
+MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
return -1;
}
@@ -1090,7 +1091,7 @@
}
static jstring
-android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
+android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
{
char date[20];
formatDateTime(seconds, date, sizeof(date));
diff --git a/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
new file mode 100644
index 0000000..2a95cfe
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
@@ -0,0 +1,319 @@
+# Copyright (C) 2013 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.
+
+#
+# Arabic (US-101 keys) keyboard layout.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base, capslock: '\u0630'
+ shift: '\u0651'
+}
+
+key 1 {
+ label: '1'
+ base: '\u0661'
+ shift: '!'
+ capslock: '1'
+}
+
+key 2 {
+ label: '2'
+ base: '\u0662'
+ shift: '@'
+ capslock: '2'
+}
+
+key 3 {
+ label: '3'
+ base: '\u0663'
+ shift: '#'
+ capslock: '3'
+}
+
+key 4 {
+ label: '4'
+ base: '\u0664'
+ shift: '$'
+ capslock: '4'
+}
+
+key 5 {
+ label: '5'
+ base: '\u0665'
+ shift: '%'
+ capslock: '5'
+}
+
+key 6 {
+ label: '6'
+ base: '\u0666'
+ shift: '^'
+ capslock: '6'
+}
+
+key 7 {
+ label: '7'
+ base: '\u0667'
+ shift: '&'
+ capslock: '7'
+}
+
+key 8 {
+ label: '8'
+ base: '\u0668'
+ shift: '*'
+ capslock: '8'
+}
+
+key 9 {
+ label: '9'
+ base: '\u0669'
+ shift: '('
+ capslock: '9'
+}
+
+key 0 {
+ label: '0'
+ base: '\u0660'
+ shift: ')'
+ capslock: '0'
+}
+
+key MINUS {
+ label: '-'
+ base, capslock: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base, capslock: '='
+ shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base, capslock: '\u0636'
+ shift: '\u064e'
+}
+
+key W {
+ label: 'W'
+ base, capslock: '\u0635'
+ shift: '\u064b'
+}
+
+key E {
+ label: 'E'
+ base, capslock: '\u062b'
+ shift: '\u064f'
+}
+
+key R {
+ label: 'R'
+ base, capslock: '\u0642'
+ shift: '\u064c'
+}
+
+key T {
+ label: 'T'
+ base, capslock: '\u0641'
+ shift: '\ufef9'
+}
+
+key Y {
+ label: 'Y'
+ base, capslock: '\u063a'
+ shift: '\u0625'
+}
+
+key U {
+ label: 'U'
+ base, capslock: '\u0639'
+ shift: '\u2018'
+}
+
+key I {
+ label: 'I'
+ base, capslock: '\u0647'
+ shift: '\u00f7'
+}
+
+key O {
+ label: 'O'
+ base, capslock: '\u062e'
+ shift: '\u00d7'
+}
+
+key P {
+ label: 'P'
+ base, capslock: '\u062d'
+ shift: '\u061b'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base, capslock: '\u062c'
+ shift: '<'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base, capslock: '\u062f'
+ shift: '>'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base, capslock: '\\'
+ shift: '|'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base, capslock: '\u0634'
+ shift: '\u0650'
+}
+
+key S {
+ label: 'S'
+ base, capslock: '\u0633'
+ shift: '\u064d'
+}
+
+key D {
+ label: 'D'
+ base, capslock: '\u064a'
+ shift: ']'
+}
+
+key F {
+ label: 'F'
+ base, capslock: '\u0628'
+ shift: '['
+}
+
+key G {
+ label: 'G'
+ base, capslock: '\u0644'
+ shift: '\ufef7'
+}
+
+key H {
+ label: 'H'
+ base, capslock: '\u0627'
+ shift: '\u0623'
+}
+
+key J {
+ label: 'J'
+ base, capslock: '\u062a'
+ shift: '\u0640'
+}
+
+key K {
+ label: 'K'
+ base, capslock: '\u0646'
+ shift: '\u060c'
+}
+
+key L {
+ label: 'L'
+ base, capslock: '\u0645'
+ shift: '/'
+}
+
+key SEMICOLON {
+ label: ';'
+ base, capslock: '\u0643'
+ shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base, capslock: '\u0637'
+ shift: '"'
+}
+
+### ROW 4
+
+key Z {
+ label: 'Z'
+ base, capslock: '\u0626'
+ shift: '~'
+}
+
+key X {
+ label: 'X'
+ base, capslock: '\u0621'
+ shift: '\u0652'
+}
+
+key C {
+ label: 'C'
+ base, capslock: '\u0624'
+ shift: '}'
+}
+
+key V {
+ label: 'V'
+ base, capslock: '\u0631'
+ shift: '{'
+}
+
+key B {
+ label: 'B'
+ base, capslock: '\ufefb'
+ shift: '\ufef5'
+}
+
+key N {
+ label: 'N'
+ base, capslock: '\u0649'
+ shift: '\u0622'
+}
+
+key M {
+ label: 'M'
+ base, capslock: '\u0629'
+ shift: '\u2019'
+}
+
+key COMMA {
+ label: ','
+ base, capslock: '\u0648'
+ shift: ','
+}
+
+key PERIOD {
+ label: '.'
+ base, capslock: '\u0632'
+ shift: '.'
+}
+
+key SLASH {
+ label: '/'
+ base, capslock: '\u0638'
+ shift: '\u061f'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_greek.kcm b/packages/InputDevices/res/raw/keyboard_layout_greek.kcm
new file mode 100644
index 0000000..a7684e1
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_greek.kcm
@@ -0,0 +1,338 @@
+# Copyright (C) 2013 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.
+
+#
+# Greek (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base, capslock: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base, capslock: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base, capslock: '2'
+ shift: '@'
+ ralt: '\u00b2'
+}
+
+key 3 {
+ label: '3'
+ base, capslock: '3'
+ shift: '#'
+ ralt: '\u00b3'
+}
+
+key 4 {
+ label: '4'
+ base, capslock: '4'
+ shift: '$'
+ ralt: '\u00a3'
+}
+
+key 5 {
+ label: '5'
+ base, capslock: '5'
+ shift: '%'
+ ralt: '\u00a7'
+}
+
+key 6 {
+ label: '6'
+ base, capslock: '6'
+ shift: '^'
+ ralt: '\u00b6'
+}
+
+key 7 {
+ label: '7'
+ base, capslock: '7'
+ shift: '&'
+}
+
+key 8 {
+ label: '8'
+ base, capslock: '8'
+ shift: '*'
+ ralt: '\u00a4'
+}
+
+key 9 {
+ label: '9'
+ base, capslock: '9'
+ shift: '('
+ ralt: '\u00a6'
+}
+
+key 0 {
+ label: '0'
+ base, capslock: '0'
+ shift: ')'
+ ralt: '\u00b0'
+}
+
+key MINUS {
+ label: '-'
+ base, capslock: '-'
+ shift: '_'
+ ralt: '\u00b1'
+}
+
+key EQUALS {
+ label: '='
+ base, capslock: '='
+ shift: '+'
+ ralt: '\u00bd'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base, capslock: ';'
+ shift: ':'
+}
+
+key W {
+ label: 'W'
+ base, capslock: '\u03c2'
+ shift: '\u0385'
+}
+
+key E {
+ label: 'E'
+ base: '\u03b5'
+ shift, capslock: '\u0395'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: '\u03c1'
+ shift, capslock: '\u03a1'
+ ralt: '\u00ae'
+}
+
+key T {
+ label: 'T'
+ base: '\u03c4'
+ shift, capslock: '\u03a4'
+}
+
+key Y {
+ label: 'Y'
+ base: '\u03c5'
+ shift, capslock: '\u03a5'
+ ralt: '\u00a5'
+}
+
+key U {
+ label: 'U'
+ base: '\u03b8'
+ shift, capslock: '\u0398'
+}
+
+key I {
+ label: 'I'
+ base: '\u03b9'
+ shift, capslock: '\u0399'
+}
+
+key O {
+ label: 'O'
+ base: '\u03bf'
+ shift, capslock: '\u039f'
+}
+
+key P {
+ label: 'P'
+ base: '\u03c0'
+ shift, capslock: '\u03a0'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base, capslock: '['
+ shift: '{'
+ ralt: '\u00ab'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base, capslock: ']'
+ shift: '}'
+ ralt: '\u00bb'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: '\u03b1'
+ shift, capslock: '\u0391'
+}
+
+key S {
+ label: 'S'
+ base: '\u03c3'
+ shift, capslock: '\u03a3'
+}
+
+key D {
+ label: 'D'
+ base: '\u03b4'
+ shift, capslock: '\u0394'
+}
+
+key F {
+ label: 'F'
+ base: '\u03c6'
+ shift, capslock: '\u03a6'
+}
+
+key G {
+ label: 'G'
+ base: '\u03b3'
+ shift, capslock: '\u0393'
+}
+
+key H {
+ label: 'H'
+ base: '\u03b7'
+ shift, capslock: '\u0397'
+}
+
+key J {
+ label: 'J'
+ base: '\u03be'
+ shift, capslock: '\u039e'
+}
+
+key K {
+ label: 'K'
+ base: '\u03ba'
+ shift, capslock: '\u039a'
+}
+
+key L {
+ label: 'L'
+ base: '\u03bb'
+ shift, capslock: '\u039b'
+}
+
+key SEMICOLON {
+ label: ';'
+ base, capslock: '\u0301'
+#should be \u0384 (greek tonos)
+ shift: '\u0308'
+ ralt: '\u0385'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base, capslock: '\''
+ shift: '"'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base, capslock: '\\'
+ shift: '|'
+ ralt: '\u00ac'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base, capslock: '<'
+ shift: '>'
+ ralt: '\\'
+ shift+ralt: '|'
+}
+
+key Z {
+ label: 'Z'
+ base: '\u03b6'
+ shift, capslock: '\u0396'
+}
+
+key X {
+ label: 'X'
+ base: '\u03c7'
+ shift, capslock: '\u03a7'
+}
+
+key C {
+ label: 'C'
+ base: '\u03c8'
+ shift, capslock: '\u03a8'
+ ralt: '\u00a9'
+}
+
+key V {
+ label: 'V'
+ base: '\u03c9'
+ shift, capslock: '\u03a9'
+}
+
+key B {
+ label: 'B'
+ base: '\u03b2'
+ shift, capslock: '\u0392'
+}
+
+key N {
+ label: 'N'
+ base: '\u03bd'
+ shift, capslock: '\u039d'
+}
+
+key M {
+ label: 'M'
+ base: '\u03bc'
+ shift, capslock: '\u039c'
+}
+
+key COMMA {
+ label: ','
+ base, capslock: ','
+ shift: '<'
+}
+
+key PERIOD {
+ label: '.'
+ base, capslock: '.'
+ shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base, capslock: '/'
+ shift: '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
new file mode 100644
index 0000000..cd3a4b9
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
@@ -0,0 +1,341 @@
+# Copyright (C) 2013 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.
+
+#
+# Hebrew (based EU) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: ';'
+ shift: '~'
+ shift+capslock: '\u05b0'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ shift+capslock: '\u05b1'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '@'
+ shift+capslock: '\u05b2'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+ shift+capslock: '\u05b3'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+ ralt: '\u20aa'
+ shift+capslock: '\u05b4'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+ shift+capslock: '\u05b5'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '^'
+ shift+capslock: '\u05b6'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '&'
+ shift+capslock: '\u05b7'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+ shift+capslock: '\u05b8'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+ shift+capslock: '\u05c2'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+ shift+capslock: '\u05c1'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '\u05bf'
+ shift+capslock: '\u05b9'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+ shift+capslock: '\u05bc'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: '/'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: '\u0027'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: '\u05e7'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: '\u05e8'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: '\u05d0'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: '\u05d8'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: '\u05d5'
+ shift, capslock: 'U'
+ ralt: '\u05f0'
+}
+
+key I {
+ label: 'I'
+ base: '\u05df'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: '\u05dd'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: '\u05e4'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base, capslock: '['
+ shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base, capslock: ']'
+ shift: '}'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: '\u05e9'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: '\u05d3'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: '\u05d2'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: '\u05db'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: '\u05e2'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: '\u05d9'
+ shift, capslock: 'H'
+ ralt: '\u05f2'
+}
+
+key J {
+ label: 'J'
+ base: '\u05d7'
+ shift, capslock: 'J'
+ ralt: '\u05f1'
+}
+
+key K {
+ label: 'K'
+ base: '\u05dc'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: '\u05da'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: '\u05e3'
+ shift: ':'
+ capslock: ';'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base: ','
+ shift: '"'
+ capslock: '\''
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '\\'
+ base, capslock: '\\'
+ shift: '|'
+}
+
+key Z {
+ label: 'Z'
+ base: '\u05d6'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: '\u05e1'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: '\u05d1'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: '\u05d4'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: '\u05e0'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: '\u05de'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: '\u05e6'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: '\u05ea'
+ shift: '<'
+ capslock: ','
+}
+
+key PERIOD {
+ label: '.'
+ base: '\u05e5'
+ shift: '>'
+ capslock: '.'
+}
+
+key SLASH {
+ label: '/'
+ base: '.'
+ shift: '?'
+ capslock: '/'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm b/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm
new file mode 100644
index 0000000..72ca333
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm
@@ -0,0 +1,338 @@
+# Copyright (C) 2013 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.
+
+#
+# Lithuanian (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '\u0105'
+ shift, capslock: '\u0104'
+ ralt: '1'
+ shift+ralt: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '\u010d'
+ shift, capslock: '\u010c'
+ ralt: '2'
+ shift+ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '\u0119'
+ shift, capslock: '\u0118'
+ ralt: '3'
+ shift+ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '\u0117'
+ shift, capslock: '\u0116'
+ ralt: '4'
+ shift+ralt: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '\u012f'
+ shift, capslock: '\u012e'
+ ralt: '5'
+ shift+ralt: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '\u0161'
+ shift, capslock: '\u0160'
+ ralt: '6'
+ shift+ralt: '\u0302'
+}
+
+key 7 {
+ label: '7'
+ base: '\u0173'
+ shift, capslock: '\u0172'
+ ralt: '7'
+ shift+ralt: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '\u016b'
+ shift, capslock: '\u016a'
+ ralt: '8'
+ shift+ralt: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+ ralt: '9'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+ ralt: '0'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '\u017e'
+ shift, capslock: '\u017d'
+ ralt: '='
+ shift+ralt: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base: '['
+ shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base: ']'
+ shift: '}'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base: '\''
+ shift: '"'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '<'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm b/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm
new file mode 100644
index 0000000..16eb53f
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm
@@ -0,0 +1,325 @@
+# Copyright (C) 2013 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.
+
+#
+# Spanish (Latin) (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '|'
+ base: '|'
+ shift: '\u00ba'
+ ralt: '\u00ac'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '&'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '/'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '('
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: ')'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: '='
+}
+
+key MINUS {
+ label: '\''
+ base: '\''
+ shift: '?'
+ ralt: '\\'
+}
+
+key EQUALS {
+ label: '\u00bf'
+ base: '\u00bf'
+ shift: '\u00a1'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+ ralt: '@'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u00b4'
+ base: '\u0301'
+ shift: '\u0308'
+ ralt: '['
+}
+
+key RIGHT_BRACKET {
+ label: '+'
+ base: '+'
+ shift: '*'
+ ralt: '\u0303'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u00d1'
+ base: '\u00f1'
+ shift, capslock: '\u00d1'
+}
+
+key APOSTROPHE {
+ label: '{'
+ base: '{'
+ shift: '['
+ ralt: '\u0302'
+}
+
+key BACKSLASH {
+ label: '}'
+ base: '}'
+ shift: ']'
+ ralt: '\u0300'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: ';'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: ':'
+}
+
+key SLASH {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 54c18f1..6239336 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -98,4 +98,19 @@
<!-- Ukrainian keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_ukrainian">Ukrainian</string>
+
+ <!-- Arabic keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_arabic">Arabic</string>
+
+ <!-- Greek keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_greek">Greek</string>
+
+ <!-- Hebrew keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_hebrew">Hebrew</string>
+
+ <!-- Lithuanian keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_lithuanian">Lithuanian</string>
+
+ <!-- Spanish (Latin) keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_spanish_latin">Spanish (Latin)</string>
</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 1f48a36..dc1db0b 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -123,4 +123,24 @@
<keyboard-layout android:name="keyboard_layout_ukrainian"
android:label="@string/keyboard_layout_ukrainian"
android:keyboardLayout="@raw/keyboard_layout_ukrainian" />
+
+ <keyboard-layout android:name="keyboard_layout_arabic"
+ android:label="@string/keyboard_layout_arabic"
+ android:keyboardLayout="@raw/keyboard_layout_arabic" />
+
+ <keyboard-layout android:name="keyboard_layout_greek"
+ android:label="@string/keyboard_layout_greek"
+ android:keyboardLayout="@raw/keyboard_layout_greek" />
+
+ <keyboard-layout android:name="keyboard_layout_hebrew"
+ android:label="@string/keyboard_layout_hebrew"
+ android:keyboardLayout="@raw/keyboard_layout_hebrew" />
+
+ <keyboard-layout android:name="keyboard_layout_lithuanian"
+ android:label="@string/keyboard_layout_lithuanian"
+ android:keyboardLayout="@raw/keyboard_layout_lithuanian" />
+
+ <keyboard-layout android:name="keyboard_layout_spanish_latin"
+ android:label="@string/keyboard_layout_spanish_latin"
+ android:keyboardLayout="@raw/keyboard_layout_spanish_latin" />
</keyboard-layouts>
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 7c0735b..4db7d4d 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -121,13 +121,14 @@
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
context.registerReceiver(mBroadcastReceiver, filter);
+ ConnectivityManager cm = (ConnectivityManager)
+ context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+
// get notified of phone state changes
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
- ConnectivityManager cm = (ConnectivityManager)
- context.getSystemService(Context.CONNECTIVITY_SERVICE);
- mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
mAirplaneModeObserver);
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index c9cbe3e..d6841c8 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -232,9 +232,13 @@
validate();
//android.util.Log.v("rs", "set surface " + sur + " w=" + w + ", h=" + h);
+ Surface s = null;
+ if (sur != null) {
+ s = new Surface(sur);
+ }
mWidth = w;
mHeight = h;
- nContextSetSurfaceTexture(w, h, sur);
+ nContextSetSurface(w, h, s);
}
/**
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
index 21e706f..3e11987 100644
--- a/services/common_time/common_time_server.cpp
+++ b/services/common_time/common_time_server.cpp
@@ -590,7 +590,7 @@
for (i = 0; (i < src_len) && (offset < dst_len); ++i) {
int res;
if (0 == (i % 16)) {
- res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i);
+ res = snprintf(dst + offset, dst_len - offset, "\n%04zx :", i);
if (res < 0)
break;
offset += res;
diff --git a/services/common_time/utils.cpp b/services/common_time/utils.cpp
index ed2c77d..ddcdfe7 100644
--- a/services/common_time/utils.cpp
+++ b/services/common_time/utils.cpp
@@ -56,7 +56,7 @@
, mHeader(header) {
mRingBuffer = new Entry[mSize];
if (NULL == mRingBuffer)
- ALOGE("Failed to allocate log ring with %u entries.", mSize);
+ ALOGE("Failed to allocate log ring with %zu entries.", mSize);
}
LogRing::~LogRing() {
@@ -150,7 +150,7 @@
localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
- res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n",
+ res = snprintf(buf, sizeof(buf), "[%2zu] %s.%03ld :: %s%s\n",
i, timebuf,
mRingBuffer[ndx].first_ts.tv_usec / 1000,
mRingBuffer[ndx].s.string(),
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index fc64656..e3a3e17 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -759,7 +759,7 @@
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
ALOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d "
- "capacity: %d errno: %d)\n",
+ "capacity: %zu errno: %d)\n",
device->fd, readSize, bufferSize, capacity, errno);
deviceChanged = true;
closeDeviceLocked(device);
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 10a639e..06a57d5 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -147,7 +147,7 @@
return false;
}
if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
- ALOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
+ ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
pointerCount, MAX_POINTERS);
return false;
}
@@ -3107,7 +3107,7 @@
dump.append(INDENT "TouchedWindows:\n");
for (size_t i = 0; i < mTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTouchState.windows[i];
- dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
+ dump.appendFormat(INDENT2 "%zu: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
i, touchedWindow.windowHandle->getName().string(),
touchedWindow.pointerIds.value,
touchedWindow.targetFlags);
@@ -3122,7 +3122,7 @@
const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
- dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, "
+ dump.appendFormat(INDENT2 "%zu: name='%s', displayId=%d, "
"paused=%s, hasFocus=%s, hasWallpaper=%s, "
"visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
"frame=[%d,%d][%d,%d], scale=%f, "
@@ -3152,7 +3152,7 @@
dump.append(INDENT "MonitoringChannels:\n");
for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
const sp<InputChannel>& channel = mMonitoringChannels[i];
- dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
+ dump.appendFormat(INDENT2 "%zu: '%s'\n", i, channel->getName().string());
}
} else {
dump.append(INDENT "MonitoringChannels: <none>\n");
@@ -3201,7 +3201,7 @@
dump.append(INDENT "Connections:\n");
for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
- dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', "
+ dump.appendFormat(INDENT2 "%zu: channelName='%s', windowName='%s', "
"status=%s, monitor=%s, inputPublisherBlocked=%s\n",
i, connection->getInputChannelName(), connection->getWindowName(),
connection->getStatusLabel(), toString(connection->monitor),
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 03852a5..d86fa4f 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -1992,7 +1992,7 @@
dumpParameters(dump);
dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
- dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
+ dump.appendFormat(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
}
@@ -3372,7 +3372,7 @@
for (size_t i = 0; i < mVirtualKeys.size(); i++) {
const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
- dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
+ dump.appendFormat(INDENT4 "%zu: scanCode=%d, keyCode=%d, "
"hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
i, virtualKey.scanCode, virtualKey.keyCode,
virtualKey.hitLeft, virtualKey.hitRight,
@@ -6119,8 +6119,8 @@
&& mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
if (slotCount > MAX_SLOTS) {
- ALOGW("MultiTouch Device %s reported %d slots but the framework "
- "only supports a maximum of %d slots at this time.",
+ ALOGW("MultiTouch Device %s reported %zu slots but the framework "
+ "only supports a maximum of %zu slots at this time.",
getDeviceName().string(), slotCount, MAX_SLOTS);
slotCount = MAX_SLOTS;
}
@@ -6292,7 +6292,7 @@
// If there are too many axes, start dropping them.
// Prefer to keep explicitly mapped axes.
if (mAxes.size() > PointerCoords::MAX_AXES) {
- ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
+ ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
pruneAxes(true);
pruneAxes(false);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index d895137..ade8414 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -46,6 +46,7 @@
import com.android.internal.R;
import com.android.internal.os.BinderInternal;
+import com.android.internal.os.Zygote;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accounts.AccountManagerService;
@@ -71,7 +72,6 @@
import com.android.server.wm.WindowManagerService;
import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
import java.io.File;
import java.util.Timer;
@@ -824,7 +824,7 @@
if (safeMode) {
ActivityManagerService.self().enterSafeMode();
// Post the safe mode state in the Zygote class
- Zygote.systemInSafeMode = true;
+ SystemServer.inSafeMode = true;
// Disable the JIT for the system_server process
VMRuntime.getRuntime().disableJitCompilation();
} else {
@@ -1117,6 +1117,11 @@
// give any timezone code room without going into negative time.
private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
+ /**
+ * When set, all subsequent apps will be launched in safe mode.
+ */
+ public static boolean inSafeMode;
+
/**
* Called to initialize native system services.
*/
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 97696a5..2b0c0c9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -38,6 +38,7 @@
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.TransferPipe;
+import com.android.internal.os.Zygote;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.MemInfoReader;
@@ -57,8 +58,6 @@
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
-import dalvik.system.Zygote;
-
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -2768,7 +2767,7 @@
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
- Zygote.systemInSafeMode == true) {
+ SystemServer.inSafeMode == true) {
debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
}
if ("1".equals(SystemProperties.get("debug.checkjni"))) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d651a62..07c2201 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1142,6 +1142,7 @@
// At this point, nothing else needs to be shown
if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
behindFullscreen = true;
+ showHomeBehindStack = false;
} else if (isActivityOverHome(r)) {
if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
showHomeBehindStack = true;
@@ -2624,6 +2625,9 @@
if (mResumedActivity == r) {
mResumedActivity = null;
}
+ if (mPausingActivity == r) {
+ mPausingActivity = null;
+ }
if (mService.mFocusedActivity == r) {
mService.mFocusedActivity = null;
}
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
old mode 100644
new mode 100755
index 483b4a0..93de0a6
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1425,6 +1425,7 @@
r.resultTo = null;
}
+ boolean switchStackFromBg = false;
boolean addingToTask = false;
boolean movedHome = false;
TaskRecord reuseTask = null;
@@ -1486,6 +1487,11 @@
}
options = null;
}
+ } else {
+ switchStackFromBg = lastStack != targetStack;
+ if (DEBUG_TASKS) Slog.d(TAG, "Caller " + sourceRecord
+ + " is not top task, it may not move " + r
+ + " to front, switchStack=" + switchStackFromBg);
}
// If the caller has requested that the target task be
// reset, then do so.
@@ -1593,6 +1599,10 @@
// don't use that intent!) And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
+ if (switchStackFromBg) {
+ moveHomeStack(lastStack.isHomeStack());
+ targetStack = lastStack;
+ }
targetStack.resumeTopActivityLocked(null, options);
} else {
ActivityOptions.abort(options);
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 4b087cc..8cd9d93 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -397,7 +397,14 @@
return execute(builder.toString());
}
- public boolean restoreconData() {
- return (execute("restorecondata") == 0);
+ public boolean restoreconData(String pkgName, String seinfo, int uid) {
+ StringBuilder builder = new StringBuilder("restorecondata");
+ builder.append(' ');
+ builder.append(pkgName);
+ builder.append(' ');
+ builder.append(seinfo != null ? seinfo : "!");
+ builder.append(' ');
+ builder.append(uid);
+ return (execute(builder.toString()) == 0);
}
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 5dded57..f33f7394 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -393,6 +393,9 @@
// If mac_permissions.xml was found for seinfo labeling.
boolean mFoundPolicyFile;
+ // If a recursive restorecon of /data/data/<pkg> is needed.
+ private boolean mShouldRestoreconData = SELinuxMMAC.shouldRestorecon();
+
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
@@ -1486,13 +1489,6 @@
// can downgrade to reader
mSettings.writeLPr();
- if (SELinuxMMAC.shouldRestorecon()) {
- Slog.i(TAG, "Relabeling of /data/data and /data/user issued.");
- if (mInstaller.restoreconData()) {
- SELinuxMMAC.setRestoreconDone();
- }
- }
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
@@ -4617,6 +4613,11 @@
}
}
pkg.applicationInfo.dataDir = dataPath.getPath();
+ if (mShouldRestoreconData) {
+ Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
+ mInstaller.restoreconData(pkg.packageName, pkg.applicationInfo.seinfo,
+ pkg.applicationInfo.uid);
+ }
} else {
if (DEBUG_PACKAGE_SCANNING) {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
@@ -11062,6 +11063,10 @@
*/
public void scanAvailableAsecs() {
updateExternalMediaStatusInner(true, false, false);
+ if (mShouldRestoreconData) {
+ SELinuxMMAC.setRestoreconDone();
+ mShouldRestoreconData = false;
+ }
}
/*
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index e599409..ed025e1 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1427,6 +1427,7 @@
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
// system/core/run-as/run-as.c
// system/core/sdcard/sdcard.c
+ // external/libselinux/src/android.c:package_info_init()
//
sb.setLength(0);
sb.append(ai.packageName);
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index c26a516..a58b00bce 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -365,7 +365,9 @@
int result = impl->set(type, &ts);
if (result < 0)
{
- ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
+ ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
+ static_cast<long long>(seconds),
+ static_cast<long long>(nanoseconds), strerror(errno));
}
}
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 323e0ac..1c75658 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -101,8 +101,93 @@
/** Unknown error or not specified */
public static final int ERROR_UNSPECIFIED = 36;
+ /** Smallest valid value for call disconnect codes. */
+ public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
+ /** Largest valid value for call disconnect codes. */
+ public static final int MAXIMUM_VALID_VALUE = ERROR_UNSPECIFIED;
+
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
// Do nothing.
}
+
+ /** Returns descriptive string for the specified disconnect cause. */
+ public static String toString(int cause) {
+ switch (cause) {
+ case NOT_DISCONNECTED:
+ return "NOT_DISCONNECTED";
+ case INCOMING_MISSED:
+ return "INCOMING_MISSED";
+ case NORMAL:
+ return "NORMAL";
+ case LOCAL:
+ return "LOCAL";
+ case BUSY:
+ return "BUSY";
+ case CONGESTION:
+ return "CONGESTION";
+ case INVALID_NUMBER:
+ return "INVALID_NUMBER";
+ case NUMBER_UNREACHABLE:
+ return "NUMBER_UNREACHABLE";
+ case SERVER_UNREACHABLE:
+ return "SERVER_UNREACHABLE";
+ case INVALID_CREDENTIALS:
+ return "INVALID_CREDENTIALS";
+ case OUT_OF_NETWORK:
+ return "OUT_OF_NETWORK";
+ case SERVER_ERROR:
+ return "SERVER_ERROR";
+ case TIMED_OUT:
+ return "TIMED_OUT";
+ case LOST_SIGNAL:
+ return "LOST_SIGNAL";
+ case LIMIT_EXCEEDED:
+ return "LIMIT_EXCEEDED";
+ case INCOMING_REJECTED:
+ return "INCOMING_REJECTED";
+ case POWER_OFF:
+ return "POWER_OFF";
+ case OUT_OF_SERVICE:
+ return "OUT_OF_SERVICE";
+ case ICC_ERROR:
+ return "ICC_ERROR";
+ case CALL_BARRED:
+ return "CALL_BARRED";
+ case FDN_BLOCKED:
+ return "FDN_BLOCKED";
+ case CS_RESTRICTED:
+ return "CS_RESTRICTED";
+ case CS_RESTRICTED_NORMAL:
+ return "CS_RESTRICTED_NORMAL";
+ case CS_RESTRICTED_EMERGENCY:
+ return "CS_RESTRICTED_EMERGENCY";
+ case UNOBTAINABLE_NUMBER:
+ return "UNOBTAINABLE_NUMBER";
+ case CDMA_LOCKED_UNTIL_POWER_CYCLE:
+ return "CDMA_LOCKED_UNTIL_POWER_CYCLE";
+ case CDMA_DROP:
+ return "CDMA_DROP";
+ case CDMA_INTERCEPT:
+ return "CDMA_INTERCEPT";
+ case CDMA_REORDER:
+ return "CDMA_REORDER";
+ case CDMA_SO_REJECT:
+ return "CDMA_SO_REJECT";
+ case CDMA_RETRY_ORDER:
+ return "CDMA_RETRY_ORDER";
+ case CDMA_ACCESS_FAILURE:
+ return "CDMA_ACCESS_FAILURE";
+ case CDMA_PREEMPTED:
+ return "CDMA_PREEMPTED";
+ case CDMA_NOT_EMERGENCY:
+ return "CDMA_NOT_EMERGENCY";
+ case CDMA_ACCESS_BLOCKED:
+ return "CDMA_ACCESS_BLOCKED";
+ case ERROR_UNSPECIFIED:
+ return "ERROR_UNSPECIFIED";
+ default:
+ return "INVALID";
+ }
+ }
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 38bf540..0b1f985 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1317,9 +1317,9 @@
curIsFormatted = false;
// Untranslatable strings must only exist in the default [empty] locale
if (locale.size() > 0) {
- fprintf(stderr, "aapt: warning: string '%s' in %s marked untranslatable but exists"
- " in locale '%s'\n", String8(name).string(),
- bundle->getResourceSourceDirs()[0],
+ SourcePos(in->getPrintableSource(), block.getLineNumber()).warning(
+ "string '%s' marked untranslatable but exists in locale '%s'\n",
+ String8(name).string(),
locale.string());
// hasErrors = localHasErrors = true;
} else {
@@ -1330,7 +1330,10 @@
// having no default translation.
}
} else {
- outTable->addLocalization(name, locale);
+ outTable->addLocalization(
+ name,
+ locale,
+ SourcePos(in->getPrintableSource(), block.getLineNumber()));
}
if (formatted == false16) {
@@ -2570,9 +2573,9 @@
void
-ResourceTable::addLocalization(const String16& name, const String8& locale)
+ResourceTable::addLocalization(const String16& name, const String8& locale, const SourcePos& src)
{
- mLocalizations[name].insert(locale);
+ mLocalizations[name][locale] = src;
}
@@ -2592,21 +2595,22 @@
const String8 defaultLocale;
// For all strings...
- for (map<String16, set<String8> >::iterator nameIter = mLocalizations.begin();
+ for (map<String16, map<String8, SourcePos> >::iterator nameIter = mLocalizations.begin();
nameIter != mLocalizations.end();
nameIter++) {
- const set<String8>& configSet = nameIter->second; // naming convenience
+ const map<String8, SourcePos>& configSrcMap = nameIter->second;
// Look for strings with no default localization
- if (configSet.count(defaultLocale) == 0) {
- fprintf(stdout, "aapt: warning: string '%s' has no default translation in %s; found:",
- String8(nameIter->first).string(), mBundle->getResourceSourceDirs()[0]);
- for (set<String8>::const_iterator locales = configSet.begin();
- locales != configSet.end();
- locales++) {
- fprintf(stdout, " %s", (*locales).string());
+ if (configSrcMap.count(defaultLocale) == 0) {
+ SourcePos().warning("string '%s' has no default translation.",
+ String8(nameIter->first).string());
+ if (mBundle->getVerbose()) {
+ for (map<String8, SourcePos>::const_iterator locales = configSrcMap.begin();
+ locales != configSrcMap.end();
+ locales++) {
+ locales->second.printf("locale %s found", locales->first.string());
+ }
}
- fprintf(stdout, "\n");
// !!! TODO: throw an error here in some circumstances
}
@@ -2616,6 +2620,8 @@
const char* start = allConfigs;
const char* comma;
+ set<String8> missingConfigs;
+ AaptLocaleValue locale;
do {
String8 config;
comma = strchr(start, ',');
@@ -2626,27 +2632,38 @@
config.setTo(start);
}
+ if (!locale.initFromFilterString(config)) {
+ continue;
+ }
+
// don't bother with the pseudolocale "zz_ZZ"
if (config != "zz_ZZ") {
- if (configSet.find(config) == configSet.end()) {
+ if (configSrcMap.find(config) == configSrcMap.end()) {
// okay, no specific localization found. it's possible that we are
// requiring a specific regional localization [e.g. de_DE] but there is an
// available string in the generic language localization [e.g. de];
// consider that string to have fulfilled the localization requirement.
String8 region(config.string(), 2);
- if (configSet.find(region) == configSet.end()) {
- if (configSet.count(defaultLocale) == 0) {
- fprintf(stdout, "aapt: warning: "
- "**** string '%s' has no default or required localization "
- "for '%s' in %s\n",
- String8(nameIter->first).string(),
- config.string(),
- mBundle->getResourceSourceDirs()[0]);
- }
+ if (configSrcMap.find(region) == configSrcMap.end() &&
+ configSrcMap.count(defaultLocale) == 0) {
+ missingConfigs.insert(config);
}
}
}
- } while (comma != NULL);
+ } while (comma != NULL);
+
+ if (!missingConfigs.empty()) {
+ String8 configStr;
+ for (set<String8>::iterator iter = missingConfigs.begin();
+ iter != missingConfigs.end();
+ iter++) {
+ configStr.appendFormat(" %s", iter->string());
+ }
+ SourcePos().warning("string '%s' is missing %u required localizations:%s",
+ String8(nameIter->first).string(),
+ (unsigned int)missingConfigs.size(),
+ configStr.string());
+ }
}
}
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index a3e0666..75005cd 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -220,7 +220,7 @@
status_t assignResourceIds();
status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL);
- void addLocalization(const String16& name, const String8& locale);
+ void addLocalization(const String16& name, const String8& locale, const SourcePos& src);
status_t validateLocalizations(void);
status_t flatten(Bundle*, const sp<AaptFile>& dest);
@@ -551,7 +551,7 @@
Bundle* mBundle;
// key = string resource name, value = set of locales in which that name is defined
- map<String16, set<String8> > mLocalizations;
+ map<String16, map<String8, SourcePos> > mLocalizations;
};
#endif
diff --git a/tools/aapt/SourcePos.cpp b/tools/aapt/SourcePos.cpp
index e2a921c..ae25047 100644
--- a/tools/aapt/SourcePos.cpp
+++ b/tools/aapt/SourcePos.cpp
@@ -10,17 +10,20 @@
// =============================================================================
struct ErrorPos
{
+ enum Level {
+ NOTE,
+ WARNING,
+ ERROR
+ };
+
String8 file;
int line;
String8 error;
- bool fatal;
+ Level level;
ErrorPos();
ErrorPos(const ErrorPos& that);
- ErrorPos(const String8& file, int line, const String8& error, bool fatal);
- ~ErrorPos();
- bool operator<(const ErrorPos& rhs) const;
- bool operator==(const ErrorPos& rhs) const;
+ ErrorPos(const String8& file, int line, const String8& error, Level level);
ErrorPos& operator=(const ErrorPos& rhs);
void print(FILE* to) const;
@@ -29,7 +32,7 @@
static vector<ErrorPos> g_errors;
ErrorPos::ErrorPos()
- :line(-1), fatal(false)
+ :line(-1), level(NOTE)
{
}
@@ -37,61 +40,52 @@
:file(that.file),
line(that.line),
error(that.error),
- fatal(that.fatal)
+ level(that.level)
{
}
-ErrorPos::ErrorPos(const String8& f, int l, const String8& e, bool fat)
+ErrorPos::ErrorPos(const String8& f, int l, const String8& e, Level lev)
:file(f),
line(l),
error(e),
- fatal(fat)
+ level(lev)
{
}
-ErrorPos::~ErrorPos()
-{
-}
-
-bool
-ErrorPos::operator<(const ErrorPos& rhs) const
-{
- if (this->file < rhs.file) return true;
- if (this->file == rhs.file) {
- if (this->line < rhs.line) return true;
- if (this->line == rhs.line) {
- if (this->error < rhs.error) return true;
- }
- }
- return false;
-}
-
-bool
-ErrorPos::operator==(const ErrorPos& rhs) const
-{
- return this->file == rhs.file
- && this->line == rhs.line
- && this->error == rhs.error;
-}
-
ErrorPos&
ErrorPos::operator=(const ErrorPos& rhs)
{
this->file = rhs.file;
this->line = rhs.line;
this->error = rhs.error;
+ this->level = rhs.level;
return *this;
}
void
ErrorPos::print(FILE* to) const
{
- const char* type = fatal ? "error:" : "warning:";
+ const char* type = "";
+ switch (level) {
+ case NOTE:
+ type = "note: ";
+ break;
+ case WARNING:
+ type = "warning: ";
+ break;
+ case ERROR:
+ type = "error: ";
+ break;
+ }
- if (this->line >= 0) {
- fprintf(to, "%s:%d: %s %s\n", this->file.string(), this->line, type, this->error.string());
+ if (!this->file.isEmpty()) {
+ if (this->line >= 0) {
+ fprintf(to, "%s:%d: %s%s\n", this->file.string(), this->line, type, this->error.string());
+ } else {
+ fprintf(to, "%s: %s%s\n", this->file.string(), type, this->error.string());
+ }
} else {
- fprintf(to, "%s: %s %s\n", this->file.string(), type, this->error.string());
+ fprintf(to, "%s%s\n", type, this->error.string());
}
}
@@ -116,40 +110,34 @@
{
}
-int
+void
SourcePos::error(const char* fmt, ...) const
{
- int retval=0;
- char buf[1024];
va_list ap;
va_start(ap, fmt);
- retval = vsnprintf(buf, sizeof(buf), fmt, ap);
+ String8 msg = String8::formatV(fmt, ap);
va_end(ap);
- char* p = buf + retval - 1;
- while (p > buf && *p == '\n') {
- *p = '\0';
- p--;
- }
- g_errors.push_back(ErrorPos(this->file, this->line, String8(buf), true));
- return retval;
+ g_errors.push_back(ErrorPos(this->file, this->line, msg, ErrorPos::ERROR));
}
-int
+void
SourcePos::warning(const char* fmt, ...) const
{
- int retval=0;
- char buf[1024];
va_list ap;
va_start(ap, fmt);
- retval = vsnprintf(buf, sizeof(buf), fmt, ap);
+ String8 msg = String8::formatV(fmt, ap);
va_end(ap);
- char* p = buf + retval - 1;
- while (p > buf && *p == '\n') {
- *p = '\0';
- p--;
- }
- ErrorPos(this->file, this->line, String8(buf), false).print(stderr);
- return retval;
+ ErrorPos(this->file, this->line, msg, ErrorPos::WARNING).print(stderr);
+}
+
+void
+SourcePos::printf(const char* fmt, ...) const
+{
+ va_list ap;
+ va_start(ap, fmt);
+ String8 msg = String8::formatV(fmt, ap);
+ va_end(ap);
+ ErrorPos(this->file, this->line, msg, ErrorPos::NOTE).print(stderr);
}
bool
diff --git a/tools/aapt/SourcePos.h b/tools/aapt/SourcePos.h
index 33f72a9..4ce817f 100644
--- a/tools/aapt/SourcePos.h
+++ b/tools/aapt/SourcePos.h
@@ -17,8 +17,9 @@
SourcePos();
~SourcePos();
- int error(const char* fmt, ...) const;
- int warning(const char* fmt, ...) const;
+ void error(const char* fmt, ...) const;
+ void warning(const char* fmt, ...) const;
+ void printf(const char* fmt, ...) const;
static bool hasErrors();
static void printErrors(FILE* to);