summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt34
-rw-r--r--cmds/app_process/app_main.cpp28
-rw-r--r--cmds/content/src/com/android/commands/content/Content.java2
-rw-r--r--cmds/installd/commands.c12
-rw-r--r--cmds/installd/installd.c11
-rw-r--r--cmds/installd/installd.h4
-rw-r--r--cmds/interrupter/Android.mk21
-rw-r--r--cmds/interrupter/interrupter.c53
-rw-r--r--cmds/interrupter/interrupter.h79
-rw-r--r--core/java/android/app/ActivityThread.java7
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/BluetoothA2dp.java0
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/BluetoothAdapter.java0
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/BluetoothDevice.java0
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/BluetoothHeadset.java0
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/BluetoothInputDevice.java0
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/BluetoothPbap.java0
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/BluetoothProfile.java0
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/IBluetoothInputDevice.aidl0
-rw-r--r--[-rwxr-xr-x]core/java/android/bluetooth/IBluetoothManager.aidl0
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java15
-rw-r--r--core/java/android/content/res/Resources.java43
-rw-r--r--core/java/android/net/SSLCertificateSocketFactory.java8
-rw-r--r--core/java/android/os/Debug.java306
-rw-r--r--core/java/android/security/IKeystoreService.java50
-rw-r--r--core/java/android/text/format/DateFormat.java386
-rw-r--r--core/java/android/text/format/DateUtils.java298
-rw-r--r--core/java/android/text/format/Formatter.java14
-rw-r--r--core/java/android/util/FloatMath.java10
-rw-r--r--core/java/android/util/SparseArray.java18
-rw-r--r--core/java/android/webkit/BrowserFrame.java2
-rw-r--r--core/java/android/webkit/ClientCertRequestHandler.java2
-rw-r--r--core/java/android/webkit/HTML5Audio.java29
-rw-r--r--core/java/android/webkit/WebViewClassic.java4
-rw-r--r--core/java/android/widget/DigitalClock.java15
-rw-r--r--core/java/android/widget/TextClock.java111
-rw-r--r--core/java/com/android/internal/backup/LocalTransport.java5
-rw-r--r--core/jni/Android.mk4
-rw-r--r--core/jni/android_ddm_DdmHandleNativeHeap.cpp128
-rw-r--r--core/jni/android_os_Debug.cpp42
-rw-r--r--core/jni/android_os_SELinux.cpp683
-rw-r--r--core/jni/com_android_internal_os_ZygoteInit.cpp6
-rw-r--r--[-rwxr-xr-x]core/res/res/values-mcc286/config.xml0
-rw-r--r--core/res/res/values/attrs.xml4
-rw-r--r--core/res/res/xml/apns.xml2
-rw-r--r--[-rwxr-xr-x]core/res/res/xml/kg_password_kbd_numeric.xml0
-rw-r--r--core/tests/coretests/src/android/text/format/DateUtilsTest.java9
-rw-r--r--core/tests/coretests/src/android/webkit/WebkitTest.java2
-rw-r--r--[-rwxr-xr-x]data/sounds/AudioPackage10.mk0
-rw-r--r--[-rwxr-xr-x]data/sounds/AudioPackage8.mk0
-rw-r--r--[-rwxr-xr-x]data/sounds/AudioPackage9.mk0
-rw-r--r--[-rwxr-xr-x]data/sounds/alarms/ogg/Krypton.oggbin103196 -> 103196 bytes
-rw-r--r--[-rwxr-xr-x]data/sounds/alarms/wav/Argon.wavbin1345138 -> 1345138 bytes
-rw-r--r--[-rwxr-xr-x]data/sounds/alarms/wav/Carbon.wavbin1143548 -> 1143548 bytes
-rw-r--r--[-rwxr-xr-x]data/sounds/alarms/wav/Osmium.wavbin470808 -> 470808 bytes
-rw-r--r--[-rwxr-xr-x]data/sounds/alarms/wav/Platinum.wavbin1290224 -> 1290224 bytes
-rw-r--r--[-rwxr-xr-x]data/sounds/alarms/wav/Promethium.wavbin1290224 -> 1290224 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/google/play/billing/v2/billing_integrate.jd0
-rw-r--r--[-rwxr-xr-x]docs/html/images/ui/notifications/custom_message.pngbin17871 -> 17871 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/images/ui/notifications/notifications_window.pngbin10392 -> 10392 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/images/ui/notifications/status_bar.pngbin7161 -> 7161 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/training/animation/anim_card_flip.mp4bin87087 -> 87087 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/training/animation/anim_card_flip.ogvbin135105 -> 135105 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/training/animation/anim_card_flip.webmbin95870 -> 95870 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/training/animation/anim_screenslide.mp4bin205799 -> 205799 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/training/animation/anim_screenslide.ogvbin727629 -> 727629 bytes
-rw-r--r--[-rwxr-xr-x]docs/html/training/animation/anim_screenslide.webmbin131539 -> 131539 bytes
-rw-r--r--keystore/java/android/security/AndroidKeyPairGeneratorSpec.java144
-rw-r--r--keystore/java/android/security/AndroidKeyStore.java45
-rw-r--r--keystore/java/android/security/Credentials.java8
-rw-r--r--keystore/java/android/security/KeyStore.java74
-rw-r--r--keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java20
-rw-r--r--keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java4
-rw-r--r--keystore/tests/src/android/security/KeyStoreTest.java215
-rw-r--r--[-rwxr-xr-x]libs/hwui/Dither.cpp0
-rw-r--r--[-rwxr-xr-x]libs/hwui/Dither.h0
-rw-r--r--media/java/android/media/ThumbnailUtils.java2
-rw-r--r--[-rwxr-xr-x]media/jni/mediaeditor/VideoBrowserMain.c0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/Android.mk0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/AndroidManifest.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/drawable/icon.pngbin6094 -> 6094 bytes
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/drawable/stop.pngbin369 -> 369 bytes
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/layout/bassboosttest.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/layout/effectstest.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/layout/envreverbtest.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/layout/equalizertest.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/layout/presetreverbtest.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/layout/virtualizertest.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/layout/visualizertest.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/res/values/strings.xml0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java0
-rw-r--r--[-rwxr-xr-x]media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java0
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java18
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java0
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java1
-rw-r--r--[-rwxr-xr-x]policy/src/com/android/internal/policy/impl/GlobalActions.java0
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java12
-rw-r--r--preloaded-classes18
-rw-r--r--services/java/com/android/server/BackupManagerService.java14
-rw-r--r--[-rwxr-xr-x]services/java/com/android/server/BluetoothManagerService.java0
-rw-r--r--services/java/com/android/server/MountService.java2
-rw-r--r--services/java/com/android/server/Watchdog.java9
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/java/com/android/server/pm/Installer.java8
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java21
-rw-r--r--services/java/com/android/server/pm/SELinuxMMAC.java294
-rw-r--r--services/java/com/android/server/pm/Settings.java6
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java34
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java6
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pService.java2
115 files changed, 2092 insertions, 1314 deletions
diff --git a/api/current.txt b/api/current.txt
index d281f136d526..e46dbeb74db0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15910,7 +15910,7 @@ package android.os {
method public static void resetThreadGcInvocationCount();
method public static deprecated int setAllocationLimit(int);
method public static deprecated int setGlobalAllocationLimit(int);
- method public static void startAllocCounting();
+ method public static deprecated void startAllocCounting();
method public static void startMethodTracing();
method public static void startMethodTracing(java.lang.String);
method public static void startMethodTracing(java.lang.String, int);
@@ -22276,19 +22276,19 @@ package android.text.format {
method public static java.text.DateFormat getMediumDateFormat(android.content.Context);
method public static java.text.DateFormat getTimeFormat(android.content.Context);
method public static boolean is24HourFormat(android.content.Context);
- field public static final char AM_PM = 97; // 0x0061 'a'
- field public static final char CAPITAL_AM_PM = 65; // 0x0041 'A'
- field public static final char DATE = 100; // 0x0064 'd'
- field public static final char DAY = 69; // 0x0045 'E'
- field public static final char HOUR = 104; // 0x0068 'h'
- field public static final char HOUR_OF_DAY = 107; // 0x006b 'k'
- field public static final char MINUTE = 109; // 0x006d 'm'
- field public static final char MONTH = 77; // 0x004d 'M'
- field public static final char QUOTE = 39; // 0x0027 '\''
- field public static final char SECONDS = 115; // 0x0073 's'
- field public static final char STANDALONE_MONTH = 76; // 0x004c 'L'
- field public static final char TIME_ZONE = 122; // 0x007a 'z'
- field public static final char YEAR = 121; // 0x0079 'y'
+ field public static final deprecated char AM_PM = 97; // 0x0061 'a'
+ field public static final deprecated char CAPITAL_AM_PM = 65; // 0x0041 'A'
+ field public static final deprecated char DATE = 100; // 0x0064 'd'
+ field public static final deprecated char DAY = 69; // 0x0045 'E'
+ field public static final deprecated char HOUR = 104; // 0x0068 'h'
+ field public static final deprecated char HOUR_OF_DAY = 107; // 0x006b 'k'
+ field public static final deprecated char MINUTE = 109; // 0x006d 'm'
+ field public static final deprecated char MONTH = 77; // 0x004d 'M'
+ field public static final deprecated char QUOTE = 39; // 0x0027 '\''
+ field public static final deprecated char SECONDS = 115; // 0x0073 's'
+ field public static final deprecated char STANDALONE_MONTH = 76; // 0x004c 'L'
+ field public static final deprecated char TIME_ZONE = 122; // 0x007a 'z'
+ field public static final deprecated char YEAR = 121; // 0x0079 'y'
}
public class DateUtils {
@@ -29496,8 +29496,8 @@ package android.widget {
method public void setFormat12Hour(java.lang.CharSequence);
method public void setFormat24Hour(java.lang.CharSequence);
method public void setTimeZone(java.lang.String);
- field public static final java.lang.CharSequence DEFAULT_FORMAT_12_HOUR;
- field public static final java.lang.CharSequence DEFAULT_FORMAT_24_HOUR;
+ field public static final deprecated java.lang.CharSequence DEFAULT_FORMAT_12_HOUR;
+ field public static final deprecated java.lang.CharSequence DEFAULT_FORMAT_24_HOUR;
}
public class TextSwitcher extends android.widget.ViewSwitcher {
@@ -41332,8 +41332,8 @@ package java.util.zip {
public class ZipFile {
ctor public ZipFile(java.io.File) throws java.io.IOException, java.util.zip.ZipException;
- ctor public ZipFile(java.io.File, int) throws java.io.IOException;
ctor public ZipFile(java.lang.String) throws java.io.IOException;
+ ctor public ZipFile(java.io.File, int) throws java.io.IOException;
method public void close() throws java.io.IOException;
method public java.util.Enumeration<? extends java.util.zip.ZipEntry> entries();
method public java.util.zip.ZipEntry getEntry(java.lang.String);
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 6fe358c7ee54..0668be606a7e 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -13,7 +13,9 @@
#include <cutils/process_name.h>
#include <cutils/memory.h>
#include <android_runtime/AndroidRuntime.h>
+#include <sys/personality.h>
+#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -128,8 +130,32 @@ static void setArgv0(const char *argv0, const char *newArgv0)
strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
}
-int main(int argc, const char* const argv[])
+int main(int argc, char* const argv[])
{
+#ifdef __arm__
+ /*
+ * b/7188322 - Temporarily revert to the compat memory layout
+ * to avoid breaking third party apps.
+ *
+ * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
+ *
+ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466
+ * changes the kernel mapping from bottom up to top-down.
+ * This breaks some programs which improperly embed
+ * an out of date copy of Android's linker.
+ */
+ if (getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) {
+ int current = personality(0xFFFFFFFF);
+ if ((current & ADDR_COMPAT_LAYOUT) == 0) {
+ personality(current | ADDR_COMPAT_LAYOUT);
+ setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
+ execv("/system/bin/app_process", argv);
+ return -1;
+ }
+ }
+ unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
+#endif
+
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 787fbdb89062..ae39d24500e5 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -96,7 +96,7 @@ public class Content {
+ " [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>]\n"
+ " <PROJECTION> is a list of colon separated column names and is formatted:\n"
+ " <COLUMN_NAME>[:<COLUMN_NAME>...]\n"
- + " <SORT_OREDER> is the order in which rows in the result should be sorted.\n"
+ + " <SORT_ORDER> is the order in which rows in the result should be sorted.\n"
+ " Example:\n"
+ " # Select \"name\" and \"value\" columns from secure settings where \"name\" is "
+ "equal to \"new_setting\" and sort the result by name in ascending order.\n"
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 2a547102eb46..09d6f89c4b88 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -14,7 +14,7 @@
** limitations under the License.
*/
-#include <linux/capability.h>
+#include <sys/capability.h>
#include "installd.h"
#include <diskusage/dirsize.h>
#include <selinux/android.h>
@@ -28,7 +28,7 @@ dir_rec_t android_app_lib_dir;
dir_rec_t android_media_dir;
dir_rec_array_t android_system_dirs;
-int install(const char *pkgname, uid_t uid, gid_t gid)
+int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
{
char pkgdir[PKG_PATH_MAX];
char libsymlink[PKG_PATH_MAX];
@@ -91,7 +91,7 @@ int install(const char *pkgname, uid_t uid, gid_t gid)
return -1;
}
- if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
+ if (selinux_android_setfilecon2(pkgdir, pkgname, seinfo, uid) < 0) {
ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
unlink(libsymlink);
unlink(pkgdir);
@@ -184,7 +184,7 @@ int delete_user_data(const char *pkgname, uid_t persona)
return delete_dir_contents(pkgdir, 0, "lib");
}
-int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
+int make_user_data(const char *pkgname, uid_t uid, uid_t persona, const char* seinfo)
{
char pkgdir[PKG_PATH_MAX];
char applibdir[PKG_PATH_MAX];
@@ -245,7 +245,7 @@ int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
return -1;
}
- if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
+ if (selinux_android_setfilecon2(pkgdir, pkgname, seinfo, uid) < 0) {
ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
unlink(libsymlink);
unlink(pkgdir);
@@ -317,7 +317,7 @@ int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
uid = (uid_t) s.st_uid % PER_USER_RANGE;
/* Create the directory for the target */
make_user_data(name, uid + target_persona * PER_USER_RANGE,
- target_persona);
+ target_persona, NULL);
}
}
closedir(d);
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
index 21d674a03bb6..281aaabc6591 100644
--- a/cmds/installd/installd.c
+++ b/cmds/installd/installd.c
@@ -14,7 +14,7 @@
** limitations under the License.
*/
-#include <linux/capability.h>
+#include <sys/capability.h>
#include <linux/prctl.h>
#include "installd.h"
@@ -31,7 +31,7 @@ static int do_ping(char **arg, char reply[REPLY_MAX])
static int do_install(char **arg, char reply[REPLY_MAX])
{
- return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
+ return install(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */
}
static int do_dexopt(char **arg, char reply[REPLY_MAX])
@@ -103,7 +103,8 @@ static int do_rm_user_data(char **arg, char reply[REPLY_MAX])
static int do_mk_user_data(char **arg, char reply[REPLY_MAX])
{
- return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */
+ return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]);
+ /* pkgname, uid, userid, seinfo */
}
static int do_rm_user(char **arg, char reply[REPLY_MAX])
@@ -134,7 +135,7 @@ struct cmdinfo {
struct cmdinfo cmds[] = {
{ "ping", 0, do_ping },
- { "install", 3, do_install },
+ { "install", 4, do_install },
{ "dexopt", 3, do_dexopt },
{ "movedex", 2, do_move_dex },
{ "rmdex", 1, do_rm_dex },
@@ -147,7 +148,7 @@ struct cmdinfo cmds[] = {
{ "rmuserdata", 2, do_rm_user_data },
{ "movefiles", 0, do_movefiles },
{ "linklib", 3, do_linklib },
- { "mkuserdata", 3, do_mk_user_data },
+ { "mkuserdata", 4, do_mk_user_data },
{ "rmuser", 1, do_rm_user },
{ "cloneuserdata", 3, do_clone_user_data },
};
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index 0500c23fa6a4..04498efab6e3 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -192,12 +192,12 @@ int ensure_media_user_dirs(userid_t userid);
/* commands.c */
-int install(const char *pkgname, uid_t uid, gid_t gid);
+int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo);
int uninstall(const char *pkgname, uid_t persona);
int renamepkg(const char *oldpkgname, const char *newpkgname);
int fix_uid(const char *pkgname, uid_t uid, gid_t gid);
int delete_user_data(const char *pkgname, uid_t persona);
-int make_user_data(const char *pkgname, uid_t uid, uid_t persona);
+int make_user_data(const char *pkgname, uid_t uid, uid_t persona, const char* seinfo);
int delete_persona(uid_t persona);
int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy);
int delete_cache(const char *pkgname, uid_t persona);
diff --git a/cmds/interrupter/Android.mk b/cmds/interrupter/Android.mk
new file mode 100644
index 000000000000..e324627517ec
--- /dev/null
+++ b/cmds/interrupter/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ interrupter.c
+LOCAL_MODULE := interrupter
+LOCAL_MODULE_TAGS := eng tests
+LOCAL_LDFLAGS := -ldl
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ interrupter.c
+LOCAL_MODULE := interrupter
+LOCAL_MODULE_TAGS := eng tests
+LOCAL_LDFLAGS := -ldl
+
+include $(BUILD_HOST_SHARED_LIBRARY) \ No newline at end of file
diff --git a/cmds/interrupter/interrupter.c b/cmds/interrupter/interrupter.c
new file mode 100644
index 000000000000..ae555150c969
--- /dev/null
+++ b/cmds/interrupter/interrupter.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012, 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.
+ */
+
+
+/**
+ * The probability of a syscall failing from 0.0 to 1.0
+ */
+#define PROBABILITY 0.9
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/* for various intercepted calls */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* For builds on glibc */
+#define __USE_GNU
+#include <dlfcn.h>
+
+#include "interrupter.h"
+
+static int probability = PROBABILITY * RAND_MAX;
+
+static int maybe_interrupt() {
+ if (rand() < probability) {
+ return 1;
+ }
+ return 0;
+}
+
+DEFINE_INTERCEPT(read, ssize_t, int, void*, size_t);
+DEFINE_INTERCEPT(write, ssize_t, int, const void*, size_t);
+DEFINE_INTERCEPT(accept, int, int, struct sockaddr*, socklen_t*);
+DEFINE_INTERCEPT(creat, int, const char*, mode_t);
diff --git a/cmds/interrupter/interrupter.h b/cmds/interrupter/interrupter.h
new file mode 100644
index 000000000000..9ad0277eebbe
--- /dev/null
+++ b/cmds/interrupter/interrupter.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2)
+#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2)
+#define CONCATENATE2(arg1, arg2) arg1##arg2
+
+#define INTERRUPTER(sym) \
+ if (real_##sym == NULL) \
+ __init_##sym(); \
+ if (maybe_interrupt()) { \
+ errno = EINTR; \
+ return -1; \
+ }
+
+#define CALL_FUNCTION_1(sym, ret, type1) \
+ret (*real_##sym)(type1) = NULL; \
+ret sym(type1 arg1) { \
+ INTERRUPTER(sym) \
+ return real_##sym(arg1); \
+}
+
+#define CALL_FUNCTION_2(sym, ret, type1, type2) \
+ret (*real_##sym)(type1, type2) = NULL; \
+ret sym(type1 arg1, type2 arg2) { \
+ INTERRUPTER(sym) \
+ return real_##sym(arg1, arg2); \
+}
+
+#define CALL_FUNCTION_3(sym, ret, type1, type2, type3) \
+ret (*real_##sym)(type1, type2, type3) = NULL; \
+ret sym(type1 arg1, type2 arg2, type3 arg3) { \
+ INTERRUPTER(sym) \
+ return real_##sym(arg1, arg2, arg3); \
+}
+
+#define CALL_FUNCTION_4(sym, ret, type1, type2, type3, type4) \
+ret (*real_##sym)(type1, type2, type3, type4) = NULL; \
+ret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ INTERRUPTER(sym) \
+ return real_##sym(arg1, arg2, arg3, arg4); \
+}
+
+#define CALL_FUNCTION_5(sym, ret, type1, type2, type3, type4, type5) \
+ret (*real_##sym)(type1, type2, type3, type4, type5) = NULL; \
+ret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
+ INTERRUPTER(sym) \
+ return real_##sym(arg1, arg2, arg3, arg4, arg5); \
+}
+
+#define DEFINE_INTERCEPT_N(N, sym, ret, ...) \
+static void __init_##sym(void); \
+CONCATENATE(CALL_FUNCTION_, N)(sym, ret, __VA_ARGS__) \
+static void __init_##sym(void) { \
+ real_##sym = dlsym(RTLD_NEXT, #sym); \
+ if (real_##sym == NULL) { \
+ fprintf(stderr, "Error hooking " #sym ": %s\n", dlerror()); \
+ } \
+}
+
+#define INTERCEPT_NARG(...) INTERCEPT_NARG_N(__VA_ARGS__, INTERCEPT_RSEQ_N())
+#define INTERCEPT_NARG_N(...) INTERCEPT_ARG_N(__VA_ARGS__)
+#define INTERCEPT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
+#define INTERCEPT_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
+
+#define DEFINE_INTERCEPT(sym, ret, ...) DEFINE_INTERCEPT_N(INTERCEPT_NARG(__VA_ARGS__), sym, ret, __VA_ARGS__)
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d8808173497e..22fd9a9d3686 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4492,6 +4492,8 @@ public final class ActivityThread {
+ "snatched provider from the jaws of death");
}
prc.removePending = false;
+ // There is a race! It fails to remove the message, which
+ // will be handled in completeRemoveProvider().
mH.removeMessages(H.REMOVE_PROVIDER, prc);
} else {
unstableDelta = 0;
@@ -4671,6 +4673,11 @@ public final class ActivityThread {
return;
}
+ // More complicated race!! Some client managed to acquire the
+ // provider and release it before the removal was completed.
+ // Continue the removal, and abort the next remove message.
+ prc.removePending = false;
+
final IBinder jBinder = prc.holder.provider.asBinder();
ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
if (existingPrc == prc) {
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 6fdf3b47b85f..6fdf3b47b85f 100755..100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 6367e160490e..6367e160490e 100755..100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 4cc22b4ae909..4cc22b4ae909 100755..100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 793d79858c6c..793d79858c6c 100755..100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index db7e424d40ee..db7e424d40ee 100755..100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index b5280e533778..b5280e533778 100755..100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 1920efa52f87..1920efa52f87 100755..100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
diff --git a/core/java/android/bluetooth/IBluetoothInputDevice.aidl b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
index 1ebb9ca6eb12..1ebb9ca6eb12 100755..100644
--- a/core/java/android/bluetooth/IBluetoothInputDevice.aidl
+++ b/core/java/android/bluetooth/IBluetoothInputDevice.aidl
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
index ed8777c51526..ed8777c51526 100755..100644
--- a/core/java/android/bluetooth/IBluetoothManager.aidl
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 32cc7fd5aa1f..02401dc5416b 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -398,6 +398,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public String[] resourceDirs;
/**
+ * String retrieved from the seinfo tag found in selinux policy. This value
+ * is useful in setting an SELinux security context on the process as well
+ * as its data directory.
+ *
+ * {@hide}
+ */
+ public String seinfo;
+
+ /**
* Paths to all shared libraries this application is linked against. This
* field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
* PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving
@@ -477,6 +486,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
if (resourceDirs != null) {
pw.println(prefix + "resourceDirs=" + resourceDirs);
}
+ if (seinfo != null) {
+ pw.println(prefix + "seinfo=" + seinfo);
+ }
pw.println(prefix + "dataDir=" + dataDir);
if (sharedLibraryFiles != null) {
pw.println(prefix + "sharedLibraryFiles=" + sharedLibraryFiles);
@@ -544,6 +556,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
publicSourceDir = orig.publicSourceDir;
nativeLibraryDir = orig.nativeLibraryDir;
resourceDirs = orig.resourceDirs;
+ seinfo = orig.seinfo;
sharedLibraryFiles = orig.sharedLibraryFiles;
dataDir = orig.dataDir;
uid = orig.uid;
@@ -583,6 +596,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeString(publicSourceDir);
dest.writeString(nativeLibraryDir);
dest.writeStringArray(resourceDirs);
+ dest.writeString(seinfo);
dest.writeStringArray(sharedLibraryFiles);
dest.writeString(dataDir);
dest.writeInt(uid);
@@ -621,6 +635,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
publicSourceDir = source.readString();
nativeLibraryDir = source.readString();
resourceDirs = source.readStringArray();
+ seinfo = source.readString();
sharedLibraryFiles = source.readStringArray();
dataDir = source.readString();
uid = source.readInt();
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index b316f230a944..0404a842a943 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -232,11 +232,13 @@ public class Resources {
}
/**
- * Return the character sequence associated with a particular resource ID for a particular
- * numerical quantity.
- *
- * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
- * Resources</a> for more on quantity strings.
+ * Returns the character sequence necessary for grammatically correct pluralization
+ * of the given resource ID for the given quantity.
+ * Note that the character sequence is selected based solely on grammatical necessity,
+ * and that such rules differ between languages. Do not assume you know which string
+ * will be returned for a given quantity. See
+ * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
+ * for more detail.
*
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
@@ -344,14 +346,17 @@ public class Resources {
}
/**
- * Return the string value associated with a particular resource ID for a particular
- * numerical quantity, substituting the format arguments as defined in
- * {@link java.util.Formatter} and {@link java.lang.String#format}. It will be
- * stripped of any styled text information.
- * {@more}
- *
- * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
- * Resources</a> for more on quantity strings.
+ * Formats the string necessary for grammatically correct pluralization
+ * of the given resource ID for the given quantity, using the given arguments.
+ * Note that the string is selected based solely on grammatical necessity,
+ * and that such rules differ between languages. Do not assume you know which string
+ * will be returned for a given quantity. See
+ * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
+ * for more detail.
+ *
+ * <p>Substitution of format arguments works as if using
+ * {@link java.util.Formatter} and {@link java.lang.String#format}.
+ * The resulting string will be stripped of any styled text information.
*
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
@@ -372,11 +377,13 @@ public class Resources {
}
/**
- * Return the string value associated with a particular resource ID for a particular
- * numerical quantity.
- *
- * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
- * Resources</a> for more on quantity strings.
+ * Returns the string necessary for grammatically correct pluralization
+ * of the given resource ID for the given quantity.
+ * Note that the string is selected based solely on grammatical necessity,
+ * and that such rules differ between languages. Do not assume you know which string
+ * will be returned for a given quantity. See
+ * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
+ * for more detail.
*
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index c0a894b6e66e..2a2f7cf81f84 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -23,8 +23,8 @@ import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.security.KeyManagementException;
+import java.security.PrivateKey;
import java.security.cert.X509Certificate;
-import java.security.interfaces.ECPrivateKey;
import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
@@ -89,7 +89,7 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
private TrustManager[] mTrustManagers = null;
private KeyManager[] mKeyManagers = null;
private byte[] mNpnProtocols = null;
- private ECPrivateKey mChannelIdPrivateKey = null;
+ private PrivateKey mChannelIdPrivateKey = null;
private final int mHandshakeTimeoutMillis;
private final SSLClientSessionCache mSessionCache;
@@ -321,7 +321,7 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
}
/**
- * Sets the {@link ECPrivateKey} to be used for TLS Channel ID by connections made by this
+ * Sets the private key to be used for TLS Channel ID by connections made by this
* factory.
*
* @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
@@ -330,7 +330,7 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
*
* @hide
*/
- public void setChannelIdPrivateKey(ECPrivateKey privateKey) {
+ public void setChannelIdPrivateKey(PrivateKey privateKey) {
mChannelIdPrivateKey = privateKey;
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e50c94813a74..2e77237451ce 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -45,7 +45,7 @@ import dalvik.system.VMDebug;
/**
- * Provides various debugging functions for Android applications, including
+ * Provides various debugging methods for Android applications, including
* tracing and allocation counts.
* <p><strong>Logging Trace Files</strong></p>
* <p>Debug can create log files that give details about an application, such as
@@ -130,7 +130,7 @@ public final class Debug
public int otherSharedDirty;
/** @hide */
- public static final int NUM_OTHER_STATS = 9;
+ public static final int NUM_OTHER_STATS = 10;
private int[] otherStats = new int[NUM_OTHER_STATS*3];
@@ -177,15 +177,16 @@ public final class Debug
/* @hide */
public static String getOtherLabel(int which) {
switch (which) {
- case 0: return "Cursor";
- case 1: return "Ashmem";
- case 2: return "Other dev";
- case 3: return ".so mmap";
- case 4: return ".jar mmap";
- case 5: return ".apk mmap";
- case 6: return ".ttf mmap";
- case 7: return ".dex mmap";
- case 8: return "Other mmap";
+ case 0: return "Stack";
+ case 1: return "Cursor";
+ case 2: return "Ashmem";
+ case 3: return "Other dev";
+ case 4: return ".so mmap";
+ case 5: return ".jar mmap";
+ case 6: return ".apk mmap";
+ case 7: return ".ttf mmap";
+ case 8: return ".dex mmap";
+ case 9: return "Other mmap";
default: return "????";
}
}
@@ -554,16 +555,19 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
/**
* Start counting the number and aggregate size of memory allocations.
*
- * <p>The {@link #startAllocCounting() start} function resets the counts and enables counting.
- * The {@link #stopAllocCounting() stop} function disables the counting so that the analysis
- * code doesn't cause additional allocations. The various <code>get</code> functions return
- * the specified value. And the various <code>reset</code> functions reset the specified
+ * <p>The {@link #startAllocCounting() start} method resets the counts and enables counting.
+ * The {@link #stopAllocCounting() stop} method disables the counting so that the analysis
+ * code doesn't cause additional allocations. The various <code>get</code> methods return
+ * the specified value. And the various <code>reset</code> methods reset the specified
* count.</p>
*
- * <p>Counts are kept for the system as a whole and for each thread.
+ * <p>Counts are kept for the system as a whole (global) and for each thread.
* The per-thread counts for threads other than the current thread
* are not cleared by the "reset" or "start" calls.</p>
+ *
+ * @deprecated Accurate counting is a burden on the runtime and may be removed.
*/
+ @Deprecated
public static void startAllocCounting() {
VMDebug.startAllocCounting();
}
@@ -577,211 +581,269 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
VMDebug.stopAllocCounting();
}
+ /**
+ * Returns the global count of objects allocated by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalAllocCount() {
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
}
+
+ /**
+ * Clears the global count of objects allocated.
+ * @see #getGlobalAllocCount()
+ */
+ public static void resetGlobalAllocCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
+ }
+
+ /**
+ * Returns the global size, in bytes, of objects allocated by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalAllocSize() {
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
}
+
+ /**
+ * Clears the global size of objects allocated.
+ * @see #getGlobalAllocCountSize()
+ */
+ public static void resetGlobalAllocSize() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
+ }
+
+ /**
+ * Returns the global count of objects freed by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalFreedCount() {
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
}
+
+ /**
+ * Clears the global count of objects freed.
+ * @see #getGlobalFreedCount()
+ */
+ public static void resetGlobalFreedCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
+ }
+
+ /**
+ * Returns the global size, in bytes, of objects freed by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalFreedSize() {
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
}
+
+ /**
+ * Clears the global size of objects freed.
+ * @see #getGlobalFreedSize()
+ */
+ public static void resetGlobalFreedSize() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
+ }
+
+ /**
+ * Returns the number of non-concurrent GC invocations between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
+ public static int getGlobalGcInvocationCount() {
+ return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
+ }
+
+ /**
+ * Clears the count of non-concurrent GC invocations.
+ * @see #getGlobalGcInvocationCount()
+ */
+ public static void resetGlobalGcInvocationCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
+ }
+
+ /**
+ * Returns the number of classes successfully initialized (ie those that executed without
+ * throwing an exception) between a {@link #startAllocCounting() start} and
+ * {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalClassInitCount() {
- /* number of classes that have been successfully initialized */
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
}
+
+ /**
+ * Clears the count of classes initialized.
+ * @see #getGlobalClassInitCount()
+ */
+ public static void resetGlobalClassInitCount() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
+ }
+
+ /**
+ * Returns the time spent successfully initializing classes between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
public static int getGlobalClassInitTime() {
/* cumulative elapsed time for class initialization, in usec */
return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
}
/**
- * Returns the global count of external allocation requests. The
- * external allocation tracking feature was removed in Honeycomb.
- * This method exists for compatibility and always returns 0.
- *
- * @deprecated This method is now obsolete.
+ * Clears the count of time spent initializing classes.
+ * @see #getGlobalClassInitTime()
*/
- @Deprecated
- public static int getGlobalExternalAllocCount() {
- return 0;
+ public static void resetGlobalClassInitTime() {
+ VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
}
/**
- * Returns the global count of bytes externally allocated. The
- * external allocation tracking feature was removed in Honeycomb.
* This method exists for compatibility and always returns 0.
- *
* @deprecated This method is now obsolete.
*/
@Deprecated
- public static int getGlobalExternalAllocSize() {
+ public static int getGlobalExternalAllocCount() {
return 0;
}
/**
- * Returns the global count of freed external allocation requests.
- * The external allocation tracking feature was removed in
- * Honeycomb. This method exists for compatibility and always
- * returns 0.
- *
+ * This method exists for compatibility and has no effect.
* @deprecated This method is now obsolete.
*/
@Deprecated
- public static int getGlobalExternalFreedCount() {
- return 0;
- }
+ public static void resetGlobalExternalAllocSize() {}
/**
- * Returns the global count of freed bytes from external
- * allocation requests. The external allocation tracking feature
- * was removed in Honeycomb. This method exists for compatibility
- * and always returns 0.
- *
+ * This method exists for compatibility and has no effect.
* @deprecated This method is now obsolete.
*/
@Deprecated
- public static int getGlobalExternalFreedSize() {
- return 0;
- }
-
- public static int getGlobalGcInvocationCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
- }
- public static int getThreadAllocCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
- }
- public static int getThreadAllocSize() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
- }
+ public static void resetGlobalExternalAllocCount() {}
/**
- * Returns the count of external allocation requests made by the
- * current thread. The external allocation tracking feature was
- * removed in Honeycomb. This method exists for compatibility and
- * always returns 0.
- *
+ * This method exists for compatibility and always returns 0.
* @deprecated This method is now obsolete.
*/
@Deprecated
- public static int getThreadExternalAllocCount() {
+ public static int getGlobalExternalAllocSize() {
return 0;
}
/**
- * Returns the global count of bytes externally allocated. The
- * external allocation tracking feature was removed in Honeycomb.
* This method exists for compatibility and always returns 0.
- *
* @deprecated This method is now obsolete.
*/
@Deprecated
- public static int getThreadExternalAllocSize() {
+ public static int getGlobalExternalFreedCount() {
return 0;
}
- public static int getThreadGcInvocationCount() {
- return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
- }
-
- public static void resetGlobalAllocCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_OBJECTS);
- }
- public static void resetGlobalAllocSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_ALLOCATED_BYTES);
- }
- public static void resetGlobalFreedCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_OBJECTS);
- }
- public static void resetGlobalFreedSize() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_FREED_BYTES);
- }
- public static void resetGlobalClassInitCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_COUNT);
- }
- public static void resetGlobalClassInitTime() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_CLASS_INIT_TIME);
- }
-
/**
- * Resets the global count of external allocation requests. The
- * external allocation tracking feature was removed in Honeycomb.
* This method exists for compatibility and has no effect.
- *
* @deprecated This method is now obsolete.
*/
@Deprecated
- public static void resetGlobalExternalAllocCount() {}
+ public static void resetGlobalExternalFreedCount() {}
/**
- * Resets the global count of bytes externally allocated. The
- * external allocation tracking feature was removed in Honeycomb.
* This method exists for compatibility and has no effect.
- *
* @deprecated This method is now obsolete.
*/
@Deprecated
- public static void resetGlobalExternalAllocSize() {}
+ public static int getGlobalExternalFreedSize() {
+ return 0;
+ }
/**
- * Resets the global count of freed external allocations. The
- * external allocation tracking feature was removed in Honeycomb.
* This method exists for compatibility and has no effect.
- *
* @deprecated This method is now obsolete.
*/
@Deprecated
- public static void resetGlobalExternalFreedCount() {}
+ public static void resetGlobalExternalFreedSize() {}
/**
- * Resets the global count counter of freed bytes from external
- * allocations. The external allocation tracking feature was
- * removed in Honeycomb. This method exists for compatibility and
- * has no effect.
- *
- * @deprecated This method is now obsolete.
+ * Returns the thread-local count of objects allocated by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
*/
- @Deprecated
- public static void resetGlobalExternalFreedSize() {}
-
- public static void resetGlobalGcInvocationCount() {
- VMDebug.resetAllocCount(VMDebug.KIND_GLOBAL_GC_INVOCATIONS);
+ public static int getThreadAllocCount() {
+ return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
}
+
+ /**
+ * Clears the thread-local count of objects allocated.
+ * @see #getThreadAllocCount()
+ */
public static void resetThreadAllocCount() {
VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_OBJECTS);
}
+
+ /**
+ * Returns the thread-local size of objects allocated by the runtime between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ * @return The allocated size in bytes.
+ */
+ public static int getThreadAllocSize() {
+ return VMDebug.getAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
+ }
+
+ /**
+ * Clears the thread-local count of objects allocated.
+ * @see #getThreadAllocSize()
+ */
public static void resetThreadAllocSize() {
VMDebug.resetAllocCount(VMDebug.KIND_THREAD_ALLOCATED_BYTES);
}
/**
- * Resets the count of external allocation requests made by the
- * current thread. The external allocation tracking feature was
- * removed in Honeycomb. This method exists for compatibility and
- * has no effect.
- *
+ * This method exists for compatibility and has no effect.
+ * @deprecated This method is now obsolete.
+ */
+ @Deprecated
+ public static int getThreadExternalAllocCount() {
+ return 0;
+ }
+
+ /**
+ * This method exists for compatibility and has no effect.
* @deprecated This method is now obsolete.
*/
@Deprecated
public static void resetThreadExternalAllocCount() {}
/**
- * Resets the count of bytes externally allocated by the current
- * thread. The external allocation tracking feature was removed
- * in Honeycomb. This method exists for compatibility and has no
- * effect.
- *
+ * This method exists for compatibility and has no effect.
+ * @deprecated This method is now obsolete.
+ */
+ @Deprecated
+ public static int getThreadExternalAllocSize() {
+ return 0;
+ }
+
+ /**
+ * This method exists for compatibility and has no effect.
* @deprecated This method is now obsolete.
*/
@Deprecated
public static void resetThreadExternalAllocSize() {}
+ /**
+ * Returns the number of thread-local non-concurrent GC invocations between a
+ * {@link #startAllocCounting() start} and {@link #stopAllocCounting() stop}.
+ */
+ public static int getThreadGcInvocationCount() {
+ return VMDebug.getAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
+ }
+
+ /**
+ * Clears the thread-local count of non-concurrent GC invocations.
+ * @see #getThreadGcInvocationCount()
+ */
public static void resetThreadGcInvocationCount() {
VMDebug.resetAllocCount(VMDebug.KIND_THREAD_GC_INVOCATIONS);
}
+
+ /**
+ * Clears all the global and thread-local memory allocation counters.
+ * @see #startAllocCounting()
+ */
public static void resetAllCounts() {
VMDebug.resetAllocCount(VMDebug.KIND_ALL_COUNTS);
}
@@ -1380,7 +1442,7 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
}
/**
- * @return a String describing the immediate caller of the calling function.
+ * @return a String describing the immediate caller of the calling method.
* {@hide}
*/
public static String getCaller() {
diff --git a/core/java/android/security/IKeystoreService.java b/core/java/android/security/IKeystoreService.java
index 651693a970f4..c36564373853 100644
--- a/core/java/android/security/IKeystoreService.java
+++ b/core/java/android/security/IKeystoreService.java
@@ -148,6 +148,10 @@ public interface IKeystoreService extends IInterface {
for (int i = 0; i < size; i++) {
_result[i] = _reply.readString();
}
+ int _ret = _reply.readInt();
+ if (_ret != 1) {
+ return null;
+ }
} finally {
_reply.recycle();
_data.recycle();
@@ -401,6 +405,45 @@ public interface IKeystoreService extends IInterface {
}
return _result;
}
+
+ @Override
+ public int duplicate(String srcKey, int srcUid, String destKey, int destUid)
+ throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(srcKey);
+ _data.writeInt(srcUid);
+ _data.writeString(destKey);
+ _data.writeInt(destUid);
+ mRemote.transact(Stub.TRANSACTION_duplicate, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
+
+ @Override
+ public int is_hardware_backed() throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ mRemote.transact(Stub.TRANSACTION_is_hardware_backed, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
+ }
}
private static final String DESCRIPTOR = "android.security.keystore";
@@ -425,6 +468,8 @@ public interface IKeystoreService extends IInterface {
static final int TRANSACTION_grant = IBinder.FIRST_CALL_TRANSACTION + 17;
static final int TRANSACTION_ungrant = IBinder.FIRST_CALL_TRANSACTION + 18;
static final int TRANSACTION_getmtime = IBinder.FIRST_CALL_TRANSACTION + 19;
+ static final int TRANSACTION_duplicate = IBinder.FIRST_CALL_TRANSACTION + 20;
+ static final int TRANSACTION_is_hardware_backed = IBinder.FIRST_CALL_TRANSACTION + 21;
/**
* Cast an IBinder object into an IKeystoreService interface, generating
@@ -509,4 +554,9 @@ public interface IKeystoreService extends IInterface {
public int ungrant(String name, int granteeUid) throws RemoteException;
public long getmtime(String name) throws RemoteException;
+
+ public int duplicate(String srcKey, int srcUid, String destKey, int destUid)
+ throws RemoteException;
+
+ public int is_hardware_backed() throws RemoteException;
}
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index cc676deece2e..50b1a2962a1b 100644
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -34,178 +34,82 @@ import java.text.SimpleDateFormat;
import libcore.icu.LocaleData;
/**
- Utility class for producing strings with formatted date/time.
-
- <p>
- Most callers should avoid supplying their own format strings to this
- class' {@code format} methods and rely on the correctly localized ones
- supplied by the system. This class' factory methods return
- appropriately-localized {@link java.text.DateFormat} instances, suitable
- for both formatting and parsing dates. For the canonical documentation
- of format strings, see {@link java.text.SimpleDateFormat}.
- </p>
- <p>
- The format methods in this class takes as inputs a format string and a representation of a date/time.
- The format string controls how the output is generated.
- This class only supports a subset of the full Unicode specification.
- Use {@link java.text.SimpleDateFormat} if you need more.
- Formatting characters may be repeated in order to get more detailed representations
- of that field. For instance, the format character &apos;M&apos; is used to
- represent the month. Depending on how many times that character is repeated
- you get a different representation.
- </p>
- <p>
- For the month of September:<br/>
- M -&gt; 9<br/>
- MM -&gt; 09<br/>
- MMM -&gt; Sep<br/>
- MMMM -&gt; September
- </p>
- <p>
- The effects of the duplication vary depending on the nature of the field.
- See the notes on the individual field formatters for details. For purely numeric
- fields such as <code>HOUR</code> adding more copies of the designator will
- zero-pad the value to that number of characters.
- </p>
- <p>
- For 7 minutes past the hour:<br/>
- m -&gt; 7<br/>
- mm -&gt; 07<br/>
- mmm -&gt; 007<br/>
- mmmm -&gt; 0007
- </p>
- <p>
- Examples for April 6, 1970 at 3:23am:<br/>
- &quot;MM/dd/yy h:mmaa&quot; -&gt; &quot;04/06/70 3:23am&quot<br/>
- &quot;MMM dd, yyyy h:mmaa&quot; -&gt; &quot;Apr 6, 1970 3:23am&quot<br/>
- &quot;MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;April 6, 1970 3:23am&quot<br/>
- &quot;E, MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;Mon, April 6, 1970 3:23am&<br/>
- &quot;EEEE, MMMM dd, yyyy h:mmaa&quot; -&gt; &quot;Monday, April 6, 1970 3:23am&quot;<br/>
- &quot;&apos;Noteworthy day: &apos;M/d/yy&quot; -&gt; &quot;Noteworthy day: 4/6/70&quot;
+ * Utility class for producing strings with formatted date/time.
+ *
+ * <p>Most callers should avoid supplying their own format strings to this
+ * class' {@code format} methods and rely on the correctly localized ones
+ * supplied by the system. This class' factory methods return
+ * appropriately-localized {@link java.text.DateFormat} instances, suitable
+ * for both formatting and parsing dates. For the canonical documentation
+ * of format strings, see {@link java.text.SimpleDateFormat}.
+ *
+ * <p>The {@code format} methods in this class implement a subset of Unicode
+ * <a href="http://www.unicode.org/reports/tr35/#Date_Format_Patterns">UTS #35</a> patterns.
+ * The subset currently supported by this class includes the following format characters:
+ * {@code acdEHhLKkLMmsyz}. Up to API level 17, only {@code adEhkMmszy} were supported.
+ * Note that this class incorrectly implements {@code k} as if it were {@code H} for backwards
+ * compatibility.
+ *
+ * <p>See {@link java.text.SimpleDateFormat} for more documentation
+ * about patterns, or if you need a more complete or correct implementation.
+ * Note that the non-{@code format} methods in this class are implemented by
+ * {@code SimpleDateFormat}.
*/
-
public class DateFormat {
- /**
- Text in the format string that should be copied verbatim rather that
- interpreted as formatting codes must be surrounded by the <code>QUOTE</code>
- character. If you need to embed a literal <code>QUOTE</code> character in
- the output text then use two in a row.
- */
+ /** @deprecated Use a literal {@code '} instead. */
+ @Deprecated
public static final char QUOTE = '\'';
-
- /**
- This designator indicates whether the <code>HOUR</code> field is before
- or after noon. The output is lower-case.
-
- Examples:
- a -> a or p
- aa -> am or pm
- */
+
+ /** @deprecated Use a literal {@code 'a'} instead. */
+ @Deprecated
public static final char AM_PM = 'a';
- /**
- This designator indicates whether the <code>HOUR</code> field is before
- or after noon. The output is capitalized.
-
- Examples:
- A -> A or P
- AA -> AM or PM
- */
+ /** @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'. */
+ @Deprecated
public static final char CAPITAL_AM_PM = 'A';
- /**
- This designator indicates the day of the month.
-
- Examples for the 9th of the month:
- d -> 9
- dd -> 09
- */
+ /** @deprecated Use a literal {@code 'd'} instead. */
+ @Deprecated
public static final char DATE = 'd';
- /**
- This designator indicates the name of the day of the week.
-
- Examples for Sunday:
- E -> Sun
- EEEE -> Sunday
- */
+ /** @deprecated Use a literal {@code 'E'} instead. */
+ @Deprecated
public static final char DAY = 'E';
- /**
- This designator indicates the hour of the day in 12 hour format.
-
- Examples for 3pm:
- h -> 3
- hh -> 03
- */
+ /** @deprecated Use a literal {@code 'h'} instead. */
+ @Deprecated
public static final char HOUR = 'h';
/**
- This designator indicates the hour of the day in 24 hour format.
-
- Example for 3pm:
- k -> 15
-
- Examples for midnight:
- k -> 0
- kk -> 00
+ * @deprecated Use a literal {@code 'H'} (for compatibility with {@link SimpleDateFormat}
+ * and Unicode) or {@code 'k'} (for compatibility with Android releases up to and including
+ * Jelly Bean MR-1) instead. Note that the two are incompatible.
*/
+ @Deprecated
public static final char HOUR_OF_DAY = 'k';
- /**
- This designator indicates the minute of the hour.
-
- Examples for 7 minutes past the hour:
- m -> 7
- mm -> 07
- */
+ /** @deprecated Use a literal {@code 'm'} instead. */
+ @Deprecated
public static final char MINUTE = 'm';
- /**
- This designator indicates the month of the year. See also
- {@link #STANDALONE_MONTH}.
-
- Examples for September:
- M -> 9
- MM -> 09
- MMM -> Sep
- MMMM -> September
- */
+ /** @deprecated Use a literal {@code 'M'} instead. */
+ @Deprecated
public static final char MONTH = 'M';
- /**
- This designator indicates the standalone month of the year,
- necessary in some format strings in some languages. For
- example, Russian distinguishes between the "June" in
- "June" and that in "June 2010".
- */
+ /** @deprecated Use a literal {@code 'L'} instead. */
+ @Deprecated
public static final char STANDALONE_MONTH = 'L';
- /**
- This designator indicates the seconds of the minute.
-
- Examples for 7 seconds past the minute:
- s -> 7
- ss -> 07
- */
+ /** @deprecated Use a literal {@code 's'} instead. */
+ @Deprecated
public static final char SECONDS = 's';
- /**
- This designator indicates the offset of the timezone from GMT.
-
- Example for US/Pacific timezone:
- z -> -0800
- zz -> PST
- */
+ /** @deprecated Use a literal {@code 'z'} instead. */
+ @Deprecated
public static final char TIME_ZONE = 'z';
- /**
- This designator indicates the year.
-
- Examples for 2006
- y -> 06
- yyyy -> 2006
- */
+ /** @deprecated Use a literal {@code 'y'} instead. */
+ @Deprecated
public static final char YEAR = 'y';
@@ -233,8 +137,7 @@ public class DateFormat {
}
java.text.DateFormat natural =
- java.text.DateFormat.getTimeInstance(
- java.text.DateFormat.LONG, locale);
+ java.text.DateFormat.getTimeInstance(java.text.DateFormat.LONG, locale);
if (natural instanceof SimpleDateFormat) {
SimpleDateFormat sdf = (SimpleDateFormat) natural;
@@ -267,13 +170,22 @@ public class DateFormat {
* @return the {@link java.text.DateFormat} object that properly formats the time.
*/
public static java.text.DateFormat getTimeFormat(Context context) {
+ return new java.text.SimpleDateFormat(getTimeFormatString(context));
+ }
+
+ /**
+ * Returns a String pattern that can be used to format the time according
+ * to the current locale and the user's 12-/24-hour clock preference.
+ * @param context the application context
+ * @hide
+ */
+ public static String getTimeFormatString(Context context) {
LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
- boolean is24 = is24HourFormat(context);
- return new java.text.SimpleDateFormat(is24 ? d.timeFormat24 : d.timeFormat12);
+ return is24HourFormat(context) ? d.timeFormat24 : d.timeFormat12;
}
/**
- * Returns a {@link java.text.DateFormat} object that can format the date
+ * Returns a {@link java.text.DateFormat} object that can format the date
* in short form (such as 12/31/1999) according
* to the current locale and the user's date-order preference.
* @param context the application context
@@ -298,7 +210,6 @@ public class DateFormat {
public static java.text.DateFormat getDateFormatForSetting(Context context,
String value) {
String format = getDateFormatStringForSetting(context, value);
-
return new java.text.SimpleDateFormat(format);
}
@@ -342,10 +253,10 @@ public class DateFormat {
value = context.getString(R.string.numeric_date_format);
return value;
}
-
+
/**
* Returns a {@link java.text.DateFormat} object that can format the date
- * in long form (such as December 31, 1999) for the current locale.
+ * in long form (such as {@code Monday, January 3, 2000}) for the current locale.
* @param context the application context
* @return the {@link java.text.DateFormat} object that formats the date in long form.
*/
@@ -355,7 +266,7 @@ public class DateFormat {
/**
* Returns a {@link java.text.DateFormat} object that can format the date
- * in medium form (such as Dec. 31, 1999) for the current locale.
+ * in medium form (such as {@code Jan 3, 2000}) for the current locale.
* @param context the application context
* @return the {@link java.text.DateFormat} object that formats the date in long form.
*/
@@ -365,13 +276,13 @@ public class DateFormat {
/**
* Gets the current date format stored as a char array. The array will contain
- * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order
+ * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order
* specified by the user's format preference. Note that this order is
* only appropriate for all-numeric dates; spelled-out (MEDIUM and LONG)
* dates will generally contain other punctuation, spaces, or words,
* not just the day, month, and year, and not necessarily in the same
* order returned here.
- */
+ */
public static char[] getDateFormatOrder(Context context) {
char[] order = new char[] {DATE, MONTH, YEAR};
String value = getDateFormatString(context);
@@ -401,7 +312,7 @@ public class DateFormat {
}
return order;
}
-
+
private static String getDateFormatString(Context context) {
String value = Settings.System.getString(context.getContentResolver(),
Settings.System.DATE_FORMAT);
@@ -410,7 +321,7 @@ public class DateFormat {
}
/**
- * Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a
+ * Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a
* CharSequence containing the requested date.
* @param inFormat the format string, as described in {@link android.text.format.DateFormat}
* @param inTimeInMillis in milliseconds since Jan 1, 1970 GMT
@@ -428,22 +339,20 @@ public class DateFormat {
* @return a {@link CharSequence} containing the requested text
*/
public static CharSequence format(CharSequence inFormat, Date inDate) {
- Calendar c = new GregorianCalendar();
-
+ Calendar c = new GregorianCalendar();
c.setTime(inDate);
-
return format(inFormat, c);
}
/**
* Indicates whether the specified format string contains seconds.
- *
+ *
* Always returns false if the input format is null.
- *
+ *
* @param inFormat the format string, as described in {@link android.text.format.DateFormat}
- *
+ *
* @return true if the format string contains {@link #SECONDS}, false otherwise
- *
+ *
* @hide
*/
public static boolean hasSeconds(CharSequence inFormat) {
@@ -498,24 +407,23 @@ public class DateFormat {
}
/**
- * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence
+ * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence
* containing the requested date.
* @param inFormat the format string, as described in {@link android.text.format.DateFormat}
* @param inDate the date to format
* @return a {@link CharSequence} containing the requested text
*/
public static CharSequence format(CharSequence inFormat, Calendar inDate) {
- SpannableStringBuilder s = new SpannableStringBuilder(inFormat);
- int c;
- int count;
+ SpannableStringBuilder s = new SpannableStringBuilder(inFormat);
+ int count;
+
+ LocaleData localeData = LocaleData.get(Locale.getDefault());
int len = inFormat.length();
for (int i = 0; i < len; i += count) {
- int temp;
-
count = 1;
- c = s.charAt(i);
+ int c = s.charAt(i);
if (c == QUOTE) {
count = appendQuotedText(s, i, len);
@@ -528,102 +436,105 @@ public class DateFormat {
}
String replacement;
-
switch (c) {
- case AM_PM:
- replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM));
- break;
-
- case CAPITAL_AM_PM:
- //FIXME: this is the same as AM_PM? no capital?
- replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM));
+ case 'A':
+ case 'a':
+ replacement = localeData.amPm[inDate.get(Calendar.AM_PM) - Calendar.AM];
break;
-
- case DATE:
+ case 'd':
replacement = zeroPad(inDate.get(Calendar.DATE), count);
break;
-
- case DAY:
- temp = inDate.get(Calendar.DAY_OF_WEEK);
- replacement = DateUtils.getDayOfWeekString(temp,
- count < 4 ?
- DateUtils.LENGTH_MEDIUM :
- DateUtils.LENGTH_LONG);
+ case 'c':
+ case 'E':
+ replacement = getDayOfWeekString(localeData,
+ inDate.get(Calendar.DAY_OF_WEEK), count, c);
break;
-
- case HOUR:
- temp = inDate.get(Calendar.HOUR);
-
- if (0 == temp)
- temp = 12;
-
- replacement = zeroPad(temp, count);
+ case 'K': // hour in am/pm (0-11)
+ case 'h': // hour in am/pm (1-12)
+ {
+ int hour = inDate.get(Calendar.HOUR);
+ if (c == 'h' && hour == 0) {
+ hour = 12;
+ }
+ replacement = zeroPad(hour, count);
+ }
+ break;
+ case 'H': // hour in day (0-23)
+ case 'k': // hour in day (1-24) [but see note below]
+ {
+ int hour = inDate.get(Calendar.HOUR_OF_DAY);
+ // Historically on Android 'k' was interpreted as 'H', which wasn't
+ // implemented, so pretty much all callers that want to format 24-hour
+ // times are abusing 'k'. http://b/8359981.
+ if (false && c == 'k' && hour == 0) {
+ hour = 24;
+ }
+ replacement = zeroPad(hour, count);
+ }
break;
-
- case HOUR_OF_DAY:
- replacement = zeroPad(inDate.get(Calendar.HOUR_OF_DAY), count);
+ case 'L':
+ case 'M':
+ replacement = getMonthString(localeData,
+ inDate.get(Calendar.MONTH), count, c);
break;
-
- case MINUTE:
+ case 'm':
replacement = zeroPad(inDate.get(Calendar.MINUTE), count);
break;
-
- case MONTH:
- case STANDALONE_MONTH:
- replacement = getMonthString(inDate, count, c);
- break;
-
- case SECONDS:
+ case 's':
replacement = zeroPad(inDate.get(Calendar.SECOND), count);
break;
-
- case TIME_ZONE:
- replacement = getTimeZoneString(inDate, count);
+ case 'y':
+ replacement = getYearString(inDate.get(Calendar.YEAR), count);
break;
-
- case YEAR:
- replacement = getYearString(inDate, count);
+ case 'z':
+ replacement = getTimeZoneString(inDate, count);
break;
-
default:
replacement = null;
break;
}
-
+
if (replacement != null) {
s.replace(i, i + count, replacement);
count = replacement.length(); // CARE: count is used in the for loop above
len = s.length();
}
}
-
- if (inFormat instanceof Spanned)
+
+ if (inFormat instanceof Spanned) {
return new SpannedString(s);
- else
+ } else {
return s.toString();
+ }
}
-
- private static String getMonthString(Calendar inDate, int count, int kind) {
- boolean standalone = (kind == STANDALONE_MONTH);
- int month = inDate.get(Calendar.MONTH);
-
- if (count >= 4) {
- return standalone
- ? DateUtils.getStandaloneMonthString(month, DateUtils.LENGTH_LONG)
- : DateUtils.getMonthString(month, DateUtils.LENGTH_LONG);
+
+ private static String getDayOfWeekString(LocaleData ld, int day, int count, int kind) {
+ boolean standalone = (kind == 'c');
+ if (count == 5) {
+ return standalone ? ld.tinyStandAloneWeekdayNames[day] : ld.tinyWeekdayNames[day];
+ } else if (count == 4) {
+ return standalone ? ld.longStandAloneWeekdayNames[day] : ld.longWeekdayNames[day];
+ } else {
+ return standalone ? ld.shortStandAloneWeekdayNames[day] : ld.shortWeekdayNames[day];
+ }
+ }
+
+ private static String getMonthString(LocaleData ld, int month, int count, int kind) {
+ boolean standalone = (kind == 'L');
+ if (count == 5) {
+ return standalone ? ld.tinyStandAloneMonthNames[month] : ld.tinyMonthNames[month];
+ } else if (count == 4) {
+ return standalone ? ld.longStandAloneMonthNames[month] : ld.longMonthNames[month];
} else if (count == 3) {
- return standalone
- ? DateUtils.getStandaloneMonthString(month, DateUtils.LENGTH_MEDIUM)
- : DateUtils.getMonthString(month, DateUtils.LENGTH_MEDIUM);
+ return standalone ? ld.shortStandAloneMonthNames[month] : ld.shortMonthNames[month];
} else {
// Calendar.JANUARY == 0, so add 1 to month.
return zeroPad(month+1, count);
}
}
-
+
private static String getTimeZoneString(Calendar inDate, int count) {
TimeZone tz = inDate.getTimeZone();
-
if (count < 2) { // FIXME: shouldn't this be <= 2 ?
return formatZoneOffset(inDate.get(Calendar.DST_OFFSET) +
inDate.get(Calendar.ZONE_OFFSET),
@@ -652,13 +563,12 @@ public class DateFormat {
tb.append(zeroPad(minutes, 2));
return tb.toString();
}
-
- private static String getYearString(Calendar inDate, int count) {
- int year = inDate.get(Calendar.YEAR);
+
+ private static String getYearString(int year, int count) {
return (count <= 2) ? zeroPad(year % 100, 2)
: String.format(Locale.getDefault(), "%d", year);
}
-
+
private static int appendQuotedText(SpannableStringBuilder s, int i, int len) {
if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
s.delete(i, i + 1);
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 8920b2482429..5a88cf69cdad 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -39,7 +39,6 @@ public class DateUtils
{
private static final Object sLock = new Object();
private static Configuration sLastConfig;
- private static java.text.DateFormat sStatusTimeFormat;
private static String sElapsedFormatMMSS;
private static String sElapsedFormatHMMSS;
@@ -95,14 +94,14 @@ public class DateUtils
// translated.
/**
* This is not actually the preferred 24-hour date format in all locales.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final String HOUR_MINUTE_24 = "%H:%M";
public static final String MONTH_FORMAT = "%B";
/**
* This is not actually a useful month name in all locales.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final String ABBREV_MONTH_FORMAT = "%b";
@@ -118,7 +117,7 @@ public class DateUtils
// The index is constructed from a bit-wise OR of the boolean values:
// {showTime, showYear, showWeekDay}. For example, if showYear and
// showWeekDay are both true, then the index would be 3.
- /** @deprecated do not use. */
+ /** @deprecated Do not use. */
public static final int sameYearTable[] = {
com.android.internal.R.string.same_year_md1_md2,
com.android.internal.R.string.same_year_wday1_md1_wday2_md2,
@@ -145,7 +144,7 @@ public class DateUtils
// The index is constructed from a bit-wise OR of the boolean values:
// {showTime, showYear, showWeekDay}. For example, if showYear and
// showWeekDay are both true, then the index would be 3.
- /** @deprecated do not use. */
+ /** @deprecated Do not use. */
public static final int sameMonthTable[] = {
com.android.internal.R.string.same_month_md1_md2,
com.android.internal.R.string.same_month_wday1_md1_wday2_md2,
@@ -172,7 +171,7 @@ public class DateUtils
*
* @more <p>
* e.g. "Sunday" or "January"
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_LONG = 10;
@@ -183,7 +182,7 @@ public class DateUtils
*
* @more <p>
* e.g. "Sun" or "Jan"
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_MEDIUM = 20;
@@ -195,7 +194,7 @@ public class DateUtils
* <p>e.g. "Su" or "Jan"
* <p>In most languages, the results returned for LENGTH_SHORT will be the same as
* the results returned for {@link #LENGTH_MEDIUM}.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_SHORT = 30;
@@ -204,7 +203,7 @@ public class DateUtils
* Request an even shorter abbreviated version of the name.
* Do not use this. Currently this will always return the same result
* as {@link #LENGTH_SHORT}.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_SHORTER = 40;
@@ -216,7 +215,7 @@ public class DateUtils
* <p>e.g. "S", "T", "T" or "J"
* <p>In some languages, the results returned for LENGTH_SHORTEST will be the same as
* the results returned for {@link #LENGTH_SHORT}.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static final int LENGTH_SHORTEST = 50;
@@ -232,7 +231,7 @@ public class DateUtils
* Undefined lengths will return {@link #LENGTH_MEDIUM}
* but may return something different in the future.
* @throws IndexOutOfBoundsException if the dayOfWeek is out of bounds.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static String getDayOfWeekString(int dayOfWeek, int abbrev) {
@@ -254,7 +253,7 @@ public class DateUtils
* @param ampm Either {@link Calendar#AM Calendar.AM} or {@link Calendar#PM Calendar.PM}.
* @throws IndexOutOfBoundsException if the ampm is out of bounds.
* @return Localized version of "AM" or "PM".
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static String getAMPMString(int ampm) {
@@ -270,14 +269,10 @@ public class DateUtils
* Undefined lengths will return {@link #LENGTH_MEDIUM}
* but may return something different in the future.
* @return Localized month of the year.
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
+ * @deprecated Use {@link java.text.SimpleDateFormat} instead.
*/
@Deprecated
public static String getMonthString(int month, int abbrev) {
- // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER.
- // This is a shortcut to not spam the translators with too many variations
- // of the same string. If we find that in a language the distinction
- // is necessary, we can can add more without changing this API.
LocaleData d = LocaleData.get(Locale.getDefault());
String[] names;
switch (abbrev) {
@@ -292,41 +287,6 @@ public class DateUtils
}
/**
- * Return a localized string for the month of the year, for
- * contexts where the month is not formatted together with
- * a day of the month.
- *
- * @param month One of {@link Calendar#JANUARY Calendar.JANUARY},
- * {@link Calendar#FEBRUARY Calendar.FEBRUARY}, etc.
- * @param abbrev One of {@link #LENGTH_LONG}, {@link #LENGTH_MEDIUM},
- * or {@link #LENGTH_SHORTEST}.
- * Undefined lengths will return {@link #LENGTH_MEDIUM}
- * but may return something different in the future.
- * @return Localized month of the year.
- * @hide Pending API council approval
- * @deprecated use {@link java.text.SimpleDateFormat} instead.
- */
- @Deprecated
- public static String getStandaloneMonthString(int month, int abbrev) {
- // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER.
- // This is a shortcut to not spam the translators with too many variations
- // of the same string. If we find that in a language the distinction
- // is necessary, we can can add more without changing this API.
- LocaleData d = LocaleData.get(Locale.getDefault());
- String[] names;
- switch (abbrev) {
- case LENGTH_LONG: names = d.longStandAloneMonthNames;
- break;
- case LENGTH_MEDIUM: names = d.shortMonthNames; break;
- case LENGTH_SHORT: names = d.shortMonthNames; break;
- case LENGTH_SHORTER: names = d.shortMonthNames; break;
- case LENGTH_SHORTEST: names = d.tinyMonthNames; break;
- default: names = d.shortMonthNames; break;
- }
- return names[month];
- }
-
- /**
* Returns a string describing the elapsed time since startTime.
* @param startTime some time in the past.
* @return a String object containing the elapsed time.
@@ -429,20 +389,7 @@ public class DateUtils
}
}
} else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
- count = getNumberOfDaysPassed(time, now);
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_days_ago;
- } else {
- resId = com.android.internal.R.plurals.num_days_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_days;
- } else {
- resId = com.android.internal.R.plurals.in_num_days;
- }
- }
+ return getRelativeDayString(r, time, now);
} else {
// We know that we won't be showing the time, so it is safe to pass
// in a null context.
@@ -454,24 +401,6 @@ public class DateUtils
}
/**
- * Returns the number of days passed between two dates.
- *
- * @param date1 first date
- * @param date2 second date
- * @return number of days passed between to dates.
- */
- private synchronized static long getNumberOfDaysPassed(long date1, long date2) {
- if (sThenTime == null) {
- sThenTime = new Time();
- }
- sThenTime.set(date1);
- int day1 = Time.getJulianDay(date1, sThenTime.gmtoff);
- sThenTime.set(date2);
- int day2 = Time.getJulianDay(date2, sThenTime.gmtoff);
- return Math.abs(day2 - day1);
- }
-
- /**
* Return string describing the elapsed time since startTime formatted like
* "[relative time/date], [time]".
* <p>
@@ -529,28 +458,29 @@ public class DateUtils
* today this function returns "Today", if the day was a week ago it returns "7 days ago", and
* if the day is in 2 weeks it returns "in 14 days".
*
- * @param r the resources to get the strings from
+ * @param r the resources
* @param day the relative day to describe in UTC milliseconds
* @param today the current time in UTC milliseconds
- * @return a formatting string
*/
private static final String getRelativeDayString(Resources r, long day, long today) {
+ Locale locale = r.getConfiguration().locale;
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ // TODO: use TimeZone.getOffset instead.
Time startTime = new Time();
startTime.set(day);
+ int startDay = Time.getJulianDay(day, startTime.gmtoff);
+
Time currentTime = new Time();
currentTime.set(today);
-
- int startDay = Time.getJulianDay(day, startTime.gmtoff);
int currentDay = Time.getJulianDay(today, currentTime.gmtoff);
int days = Math.abs(currentDay - startDay);
boolean past = (today > day);
// TODO: some locales name other days too, such as de_DE's "Vorgestern" (today - 2).
- Locale locale = r.getConfiguration().locale;
- if (locale == null) {
- locale = Locale.getDefault();
- }
if (days == 1) {
if (past) {
return LocaleData.get(locale).yesterday;
@@ -583,25 +513,12 @@ public class DateUtils
Configuration cfg = r.getConfiguration();
if (sLastConfig == null || !sLastConfig.equals(cfg)) {
sLastConfig = cfg;
- sStatusTimeFormat = java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT);
sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss);
sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss);
}
}
/**
- * Format a time so it appears like it would in the status bar clock.
- * @deprecated use {@link #DateFormat.getTimeFormat(Context)} instead.
- * @hide
- */
- public static final CharSequence timeString(long millis) {
- synchronized (sLock) {
- initFormatStringsLocked();
- return sStatusTimeFormat.format(millis);
- }
- }
-
- /**
* Return given duration in a human-friendly format. For example, "4
* minutes" or "1 second". Returns only largest meaningful unit of time,
* from seconds up to hours.
@@ -715,18 +632,6 @@ public class DateUtils
}
/**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static Calendar newCalendar(boolean zulu)
- {
- if (zulu)
- return Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-
- return Calendar.getInstance();
- }
-
- /**
* @return true if the supplied when is today else false
*/
public static boolean isToday(long when) {
@@ -744,127 +649,6 @@ public class DateUtils
}
/**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- * Return true if this date string is local time
- */
- public static boolean isUTC(String s)
- {
- if (s.length() == 16 && s.charAt(15) == 'Z') {
- return true;
- }
- if (s.length() == 9 && s.charAt(8) == 'Z') {
- // XXX not sure if this case possible/valid
- return true;
- }
- return false;
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- * Ensures that the time is written in UTC. The Calendar class doesn't
- * really help out with this, so this is slower than it ought to be.
- *
- * @param cal the date and time to write
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal)
- {
- TimeZone tz = TimeZone.getTimeZone("GMT");
- GregorianCalendar c = new GregorianCalendar(tz);
- c.setTimeInMillis(cal.getTimeInMillis());
- return writeDateTime(c, true);
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- *
- * @param cal the date and time to write
- * @param zulu If the calendar is in UTC, pass true, and a Z will
- * be written at the end as per RFC2445. Otherwise, the time is
- * considered in localtime.
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal, boolean zulu)
- {
- StringBuilder sb = new StringBuilder();
- sb.ensureCapacity(16);
- if (zulu) {
- sb.setLength(16);
- sb.setCharAt(15, 'Z');
- } else {
- sb.setLength(15);
- }
- return writeDateTime(cal, sb);
- }
-
- /**
- * Return a string containing the date and time in RFC2445 format.
- *
- * @param cal the date and time to write
- * @param sb a StringBuilder to use. It is assumed that setLength
- * has already been called on sb to the appropriate length
- * which is sb.setLength(zulu ? 16 : 15)
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static String writeDateTime(Calendar cal, StringBuilder sb)
- {
- int n;
-
- n = cal.get(Calendar.YEAR);
- sb.setCharAt(3, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(2, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(1, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(0, (char)('0'+n%10));
-
- n = cal.get(Calendar.MONTH) + 1;
- sb.setCharAt(5, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(4, (char)('0'+n%10));
-
- n = cal.get(Calendar.DAY_OF_MONTH);
- sb.setCharAt(7, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(6, (char)('0'+n%10));
-
- sb.setCharAt(8, 'T');
-
- n = cal.get(Calendar.HOUR_OF_DAY);
- sb.setCharAt(10, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(9, (char)('0'+n%10));
-
- n = cal.get(Calendar.MINUTE);
- sb.setCharAt(12, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(11, (char)('0'+n%10));
-
- n = cal.get(Calendar.SECOND);
- sb.setCharAt(14, (char)('0'+n%10));
- n /= 10;
- sb.setCharAt(13, (char)('0'+n%10));
-
- return sb.toString();
- }
-
- /**
- * @hide
- * @deprecated use {@link android.text.format.Time}
- */
- public static void assign(Calendar lval, Calendar rval)
- {
- // there should be a faster way.
- lval.clear();
- lval.setTimeInMillis(rval.getTimeInMillis());
- }
-
- /**
* Formats a date or a time range according to the local conventions.
* <p>
* Note that this is a convenience method. Using it involves creating an
@@ -1096,30 +880,34 @@ public class DateUtils
// computation below that'd otherwise be thrown out.
boolean isInstant = (startMillis == endMillis);
- Time startDate;
+ Calendar startCalendar, endCalendar;
+ Time startDate = new Time();
if (timeZone != null) {
- startDate = new Time(timeZone);
+ startCalendar = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
} else if (useUTC) {
- startDate = new Time(Time.TIMEZONE_UTC);
+ startCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
} else {
- startDate = new Time();
+ startCalendar = Calendar.getInstance();
}
- startDate.set(startMillis);
+ startCalendar.setTimeInMillis(startMillis);
+ setTimeFromCalendar(startDate, startCalendar);
- Time endDate;
+ Time endDate = new Time();
int dayDistance;
if (isInstant) {
endDate = startDate;
dayDistance = 0;
} else {
if (timeZone != null) {
- endDate = new Time(timeZone);
+ endCalendar = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
} else if (useUTC) {
- endDate = new Time(Time.TIMEZONE_UTC);
+ endCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
} else {
- endDate = new Time();
+ endCalendar = Calendar.getInstance();
}
- endDate.set(endMillis);
+ endCalendar.setTimeInMillis(endMillis);
+ setTimeFromCalendar(endDate, endCalendar);
+
int startJulianDay = Time.getJulianDay(startMillis, startDate.gmtoff);
int endJulianDay = Time.getJulianDay(endMillis, endDate.gmtoff);
dayDistance = endJulianDay - startJulianDay;
@@ -1462,6 +1250,20 @@ public class DateUtils
return formatter.format(fullFormat, timeString, startWeekDayString, dateString);
}
+ private static void setTimeFromCalendar(Time t, Calendar c) {
+ t.hour = c.get(Calendar.HOUR_OF_DAY);
+ t.minute = c.get(Calendar.MINUTE);
+ t.month = c.get(Calendar.MONTH);
+ t.monthDay = c.get(Calendar.DAY_OF_MONTH);
+ t.second = c.get(Calendar.SECOND);
+ t.weekDay = c.get(Calendar.DAY_OF_WEEK) - 1;
+ t.year = c.get(Calendar.YEAR);
+ t.yearDay = c.get(Calendar.DAY_OF_YEAR);
+ t.isDst = (c.get(Calendar.DST_OFFSET) != 0) ? 1 : 0;
+ t.gmtoff = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);
+ t.timezone = c.getTimeZone().getID();
+ }
+
/**
* Formats a date or a time according to the local conventions. There are
* lots of options that allow the caller to control, for example, if the
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 121c6f2f9324..9c98b98dedf4 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -95,16 +95,12 @@ public final class Formatter {
}
/**
- * Returns a string in the canonical IP format ###.###.###.### from a packed integer containing
- * the IP address. The IP address is expected to be in little-endian format (LSB first). That
- * is, 0x01020304 will return "4.3.2.1".
+ * Returns a string in the canonical IPv4 format ###.###.###.### from a packed integer
+ * containing the IP address. The IPv4 address is expected to be in little-endian
+ * format (LSB first). That is, 0x01020304 will return "4.3.2.1".
*
- * @param ipv4Address the IP address as a packed integer with LSB first.
- * @return string with canonical IP address format.
- *
- * @deprecated this method doesn't support IPv6 addresses. Prefer {@link
- * java.net.InetAddress#getHostAddress()}, which supports both IPv4 and
- * IPv6 addresses.
+ * @deprecated Use {@link java.net.InetAddress#getHostAddress()}, which supports both IPv4 and
+ * IPv6 addresses. This method does not support IPv6 addresses.
*/
@Deprecated
public static String formatIpAddress(int ipv4Address) {
diff --git a/core/java/android/util/FloatMath.java b/core/java/android/util/FloatMath.java
index 955622396aac..0ffd5bd61098 100644
--- a/core/java/android/util/FloatMath.java
+++ b/core/java/android/util/FloatMath.java
@@ -17,12 +17,10 @@
package android.util;
/**
- * Math routines similar to those found in {@link java.lang.Math}. Performs
- * computations on {@code float} values directly without incurring the overhead
- * of conversions to and from {@code double}.
- *
- * <p>On one platform, {@code FloatMath.sqrt(100)} executes in one third of the
- * time required by {@code java.lang.Math.sqrt(100)}.</p>
+ * Math routines similar to those found in {@link java.lang.Math}. On
+ * versions of Android with a JIT, these are significantly slower than
+ * the equivalent {@code Math} functions, which should be used in preference
+ * to these.
*/
public class FloatMath {
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 366abd36294d..7e8fee56ea95 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -118,7 +118,7 @@ public class SparseArray<E> implements Cloneable {
mGarbage = true;
}
}
-
+
private void gc() {
// Log.e("SparseArray", "gc start with " + mSize);
@@ -214,7 +214,7 @@ public class SparseArray<E> implements Cloneable {
/**
* Given an index in the range <code>0...size()-1</code>, returns
* the key from the <code>index</code>th key-value mapping that this
- * SparseArray stores.
+ * SparseArray stores.
*/
public int keyAt(int index) {
if (mGarbage) {
@@ -223,11 +223,11 @@ public class SparseArray<E> implements Cloneable {
return mKeys[index];
}
-
+
/**
* Given an index in the range <code>0...size()-1</code>, returns
* the value from the <code>index</code>th key-value mapping that this
- * SparseArray stores.
+ * SparseArray stores.
*/
@SuppressWarnings("unchecked")
public E valueAt(int index) {
@@ -241,7 +241,7 @@ public class SparseArray<E> implements Cloneable {
/**
* Given an index in the range <code>0...size()-1</code>, sets a new
* value for the <code>index</code>th key-value mapping that this
- * SparseArray stores.
+ * SparseArray stores.
*/
public void setValueAt(int index, E value) {
if (mGarbage) {
@@ -250,7 +250,7 @@ public class SparseArray<E> implements Cloneable {
mValues[index] = value;
}
-
+
/**
* Returns the index for which {@link #keyAt} would return the
* specified key, or a negative number if the specified
@@ -268,9 +268,11 @@ public class SparseArray<E> implements Cloneable {
* Returns an index for which {@link #valueAt} would return the
* specified key, or a negative number if no keys map to the
* specified value.
- * Beware that this is a linear search, unlike lookups by key,
+ * <p>Beware that this is a linear search, unlike lookups by key,
* and that multiple keys can map to the same value and this will
* find only one of them.
+ * <p>Note also that unlike most collections' {@code indexOf} methods,
+ * this method compares values using {@code ==} rather than {@code equals}.
*/
public int indexOfValue(E value) {
if (mGarbage) {
@@ -332,7 +334,7 @@ public class SparseArray<E> implements Cloneable {
mValues[pos] = value;
mSize = pos + 1;
}
-
+
private static int binarySearch(int[] a, int start, int len, int key) {
int high = start + len, low = start - 1, guess;
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index c3a1a17d88a1..023dfa8dafe4 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1324,7 +1324,7 @@ class BrowserFrame extends Handler {
private native void nativeSslCertErrorCancel(int handle, int certError);
native void nativeSslClientCert(int handle,
- int ctx,
+ long ctx,
byte[][] asn1DerEncodedCertificateChain);
native void nativeSslClientCert(int handle,
diff --git a/core/java/android/webkit/ClientCertRequestHandler.java b/core/java/android/webkit/ClientCertRequestHandler.java
index dac151054198..f5a60f6e871d 100644
--- a/core/java/android/webkit/ClientCertRequestHandler.java
+++ b/core/java/android/webkit/ClientCertRequestHandler.java
@@ -75,7 +75,7 @@ public final class ClientCertRequestHandler extends Handler {
/**
* Proceed with the specified private key bytes and client certificate chain.
*/
- private void setSslClientCertFromCtx(final int ctx, final byte[][] chainBytes) {
+ private void setSslClientCertFromCtx(final long ctx, final byte[][] chainBytes) {
post(new Runnable() {
public void run() {
mBrowserFrame.nativeSslClientCert(mHandle, ctx, chainBytes);
diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java
index fc5df2d5f59c..684ec073ce45 100644
--- a/core/java/android/webkit/HTML5Audio.java
+++ b/core/java/android/webkit/HTML5Audio.java
@@ -54,14 +54,15 @@ class HTML5Audio extends Handler
// The private status of the view that created this player
private IsPrivateBrowsingEnabledGetter mIsPrivateBrowsingEnabledGetter;
- private static int IDLE = 0;
- private static int INITIALIZED = 1;
- private static int PREPARED = 2;
- private static int STARTED = 4;
- private static int COMPLETE = 5;
- private static int PAUSED = 6;
- private static int STOPPED = -2;
- private static int ERROR = -1;
+ private static int IDLE = 0;
+ private static int INITIALIZED = 1;
+ private static int PREPARED = 2;
+ private static int STARTED = 4;
+ private static int COMPLETE = 5;
+ private static int PAUSED = 6;
+ private static int PAUSED_TRANSITORILY = 7;
+ private static int STOPPED = -2;
+ private static int ERROR = -1;
private int mState = IDLE;
@@ -247,7 +248,7 @@ class HTML5Audio extends Handler
// resume playback
if (mMediaPlayer == null) {
resetMediaPlayer();
- } else if (mState != ERROR && !mMediaPlayer.isPlaying()) {
+ } else if (mState == PAUSED_TRANSITORILY && !mMediaPlayer.isPlaying()) {
mMediaPlayer.start();
mState = STARTED;
}
@@ -265,7 +266,9 @@ class HTML5Audio extends Handler
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// Lost focus for a short time, but we have to stop
// playback.
- if (mState != ERROR && mMediaPlayer.isPlaying()) pause();
+ if (mState != ERROR && mMediaPlayer.isPlaying()) {
+ pause(PAUSED_TRANSITORILY);
+ }
break;
}
}
@@ -298,12 +301,16 @@ class HTML5Audio extends Handler
}
private void pause() {
+ pause(PAUSED);
+ }
+
+ private void pause(int state) {
if (mState == STARTED) {
if (mTimer != null) {
mTimer.purge();
}
mMediaPlayer.pause();
- mState = PAUSED;
+ mState = state;
}
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 7154f9580590..4db9f6c27342 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -5416,7 +5416,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
ClipData clipData = cm.getPrimaryClip();
if (clipData != null) {
ClipData.Item clipItem = clipData.getItemAt(0);
- CharSequence pasteText = clipItem.getText();
+ CharSequence pasteText = clipItem.coerceToText(mContext);
if (mInputConnection != null) {
mInputConnection.replaceSelection(pasteText);
}
@@ -8368,8 +8368,10 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mListBoxDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
+ if (mWebViewCore != null) {
mWebViewCore.sendMessage(
EventHub.SINGLE_LISTBOX_CHOICE, -2, 0);
+ }
mListBoxDialog = null;
}
});
diff --git a/core/java/android/widget/DigitalClock.java b/core/java/android/widget/DigitalClock.java
index c6b6dd68f182..b6c1e5b9532f 100644
--- a/core/java/android/widget/DigitalClock.java
+++ b/core/java/android/widget/DigitalClock.java
@@ -39,8 +39,6 @@ public class DigitalClock extends TextView {
// proportional fonts don't shake rendering
Calendar mCalendar;
- private final static String m12 = "h:mm:ss aa";
- private final static String m24 = "k:mm:ss";
@SuppressWarnings("FieldCanBeLocal") // We must keep a reference to this observer
private FormatChangeObserver mFormatChangeObserver;
@@ -102,19 +100,8 @@ public class DigitalClock extends TextView {
mTickerStopped = true;
}
- /**
- * Pulls 12/24 mode from system settings
- */
- private boolean get24HourMode() {
- return android.text.format.DateFormat.is24HourFormat(getContext());
- }
-
private void setFormat() {
- if (get24HourMode()) {
- mFormat = m24;
- } else {
- mFormat = m12;
- }
+ mFormat = DateFormat.getTimeFormatString(getContext());
}
private class FormatChangeObserver extends ContentObserver {
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index 290d9b5b4a52..2f08253e0721 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -36,21 +36,24 @@ import com.android.internal.R;
import java.util.Calendar;
import java.util.TimeZone;
+import libcore.icu.LocaleData;
+
import static android.view.ViewDebug.ExportedProperty;
import static android.widget.RemoteViews.*;
/**
* <p><code>TextClock</code> can display the current date and/or time as
* a formatted string.</p>
- *
+ *
* <p>This view honors the 24-hour format system setting. As such, it is
* possible and recommended to provide two different formatting patterns:
* one to display the date/time in 24-hour mode and one to display the
- * date/time in 12-hour mode.</p>
- *
+ * date/time in 12-hour mode. Most callers will want to use the defaults,
+ * though, which will be appropriate for the user's locale.</p>
+ *
* <p>It is possible to determine whether the system is currently in
* 24-hour mode by calling {@link #is24HourModeEnabled()}.</p>
- *
+ *
* <p>The rules used by this widget to decide how to format the date and
* time are the following:</p>
* <ul>
@@ -58,22 +61,24 @@ import static android.widget.RemoteViews.*;
* <ul>
* <li>Use the value returned by {@link #getFormat24Hour()} when non-null</li>
* <li>Otherwise, use the value returned by {@link #getFormat12Hour()} when non-null</li>
- * <li>Otherwise, use {@link #DEFAULT_FORMAT_24_HOUR}</li>
+ * <li>Otherwise, use a default value appropriate for the user's locale, such as {@code h:mm a}</li>
* </ul>
* </li>
* <li>In 12-hour mode:
* <ul>
* <li>Use the value returned by {@link #getFormat12Hour()} when non-null</li>
* <li>Otherwise, use the value returned by {@link #getFormat24Hour()} when non-null</li>
- * <li>Otherwise, use {@link #DEFAULT_FORMAT_12_HOUR}</li>
+ * <li>Otherwise, use a default value appropriate for the user's locale, such as {@code HH:mm}</li>
* </ul>
* </li>
* </ul>
- *
+ *
* <p>The {@link CharSequence} instances used as formatting patterns when calling either
* {@link #setFormat24Hour(CharSequence)} or {@link #setFormat12Hour(CharSequence)} can
- * contain styling information. To do so, use a {@link android.text.Spanned} object.</p>
- *
+ * contain styling information. To do so, use a {@link android.text.Spanned} object.
+ * Note that if you customize these strings, it is your responsibility to supply strings
+ * appropriate for formatting dates and/or times in the user's locale.</p>
+ *
* @attr ref android.R.styleable#TextClock_format12Hour
* @attr ref android.R.styleable#TextClock_format24Hour
* @attr ref android.R.styleable#TextClock_timeZone
@@ -81,32 +86,34 @@ import static android.widget.RemoteViews.*;
@RemoteView
public class TextClock extends TextView {
/**
- * The default formatting pattern in 12-hour mode. This pattenr is used
+ * The default formatting pattern in 12-hour mode. This pattern is used
* if {@link #setFormat12Hour(CharSequence)} is called with a null pattern
* or if no pattern was specified when creating an instance of this class.
- *
+ *
* This default pattern shows only the time, hours and minutes, and an am/pm
* indicator.
*
* @see #setFormat12Hour(CharSequence)
* @see #getFormat12Hour()
+ * @deprecated Let the system use locale-appropriate defaults instead.
*/
- public static final CharSequence DEFAULT_FORMAT_12_HOUR = "h:mm aa";
+ public static final CharSequence DEFAULT_FORMAT_12_HOUR = "h:mm a";
/**
- * The default formatting pattern in 24-hour mode. This pattenr is used
+ * The default formatting pattern in 24-hour mode. This pattern is used
* if {@link #setFormat24Hour(CharSequence)} is called with a null pattern
* or if no pattern was specified when creating an instance of this class.
*
* This default pattern shows only the time, hours and minutes.
- *
- * @see #setFormat24Hour(CharSequence)
- * @see #getFormat24Hour()
+ *
+ * @see #setFormat24Hour(CharSequence)
+ * @see #getFormat24Hour()
+ * @deprecated Let the system use locale-appropriate defaults instead.
*/
- public static final CharSequence DEFAULT_FORMAT_24_HOUR = "k:mm";
+ public static final CharSequence DEFAULT_FORMAT_24_HOUR = "H:mm";
- private CharSequence mFormat12 = DEFAULT_FORMAT_12_HOUR;
- private CharSequence mFormat24 = DEFAULT_FORMAT_24_HOUR;
+ private CharSequence mFormat12;
+ private CharSequence mFormat24;
@ExportedProperty
private CharSequence mFormat;
@@ -158,7 +165,7 @@ public class TextClock extends TextView {
* Creates a new clock using the default patterns
* {@link #DEFAULT_FORMAT_24_HOUR} and {@link #DEFAULT_FORMAT_12_HOUR}
* respectively for the 24-hour and 12-hour modes.
- *
+ *
* @param context The Context the view is running in, through which it can
* access the current theme, resources, etc.
*/
@@ -171,7 +178,7 @@ public class TextClock extends TextView {
/**
* Creates a new clock inflated from XML. This object's properties are
* intialized from the attributes specified in XML.
- *
+ *
* This constructor uses a default style of 0, so the only attribute values
* applied are those in the Context's Theme and the given AttributeSet.
*
@@ -201,14 +208,8 @@ public class TextClock extends TextView {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextClock, defStyle, 0);
try {
- CharSequence format;
-
- format = a.getText(R.styleable.TextClock_format12Hour);
- mFormat12 = format == null ? DEFAULT_FORMAT_12_HOUR : format;
-
- format = a.getText(R.styleable.TextClock_format24Hour);
- mFormat24 = format == null ? DEFAULT_FORMAT_24_HOUR : format;
-
+ mFormat12 = a.getText(R.styleable.TextClock_format12Hour);
+ mFormat24 = a.getText(R.styleable.TextClock_format24Hour);
mTimeZone = a.getString(R.styleable.TextClock_timeZone);
} finally {
a.recycle();
@@ -218,6 +219,16 @@ public class TextClock extends TextView {
}
private void init() {
+ if (mFormat12 == null || mFormat24 == null) {
+ LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
+ if (mFormat12 == null) {
+ mFormat12 = ld.timeFormat12;
+ }
+ if (mFormat24 == null) {
+ mFormat24 = ld.timeFormat24;
+ }
+ }
+
createTime(mTimeZone);
// Wait until onAttachedToWindow() to handle the ticker
chooseFormat(false);
@@ -235,11 +246,11 @@ public class TextClock extends TextView {
* Returns the formatting pattern used to display the date and/or time
* in 12-hour mode. The formatting pattern syntax is described in
* {@link DateFormat}.
- *
+ *
* @return A {@link CharSequence} or null.
- *
- * @see #setFormat12Hour(CharSequence)
- * @see #is24HourModeEnabled()
+ *
+ * @see #setFormat12Hour(CharSequence)
+ * @see #is24HourModeEnabled()
*/
@ExportedProperty
public CharSequence getFormat12Hour() {
@@ -257,12 +268,12 @@ public class TextClock extends TextView {
* {@link #DEFAULT_FORMAT_12_HOUR} will be used instead.
*
* @param format A date/time formatting pattern as described in {@link DateFormat}
- *
+ *
* @see #getFormat12Hour()
* @see #is24HourModeEnabled()
* @see #DEFAULT_FORMAT_12_HOUR
* @see DateFormat
- *
+ *
* @attr ref android.R.styleable#TextClock_format12Hour
*/
@RemotableViewMethod
@@ -292,7 +303,7 @@ public class TextClock extends TextView {
* Specifies the formatting pattern used to display the date and/or time
* in 24-hour mode. The formatting pattern syntax is described in
* {@link DateFormat}.
- *
+ *
* If this pattern is set to null, {@link #getFormat12Hour()} will be used
* even in 24-hour mode. If both 24-hour and 12-hour formatting patterns
* are set to null, {@link #DEFAULT_FORMAT_24_HOUR} and
@@ -301,7 +312,7 @@ public class TextClock extends TextView {
* @param format A date/time formatting pattern as described in {@link DateFormat}
*
* @see #getFormat24Hour()
- * @see #is24HourModeEnabled()
+ * @see #is24HourModeEnabled()
* @see #DEFAULT_FORMAT_24_HOUR
* @see DateFormat
*
@@ -317,22 +328,22 @@ public class TextClock extends TextView {
/**
* Indicates whether the system is currently using the 24-hour mode.
- *
+ *
* When the system is in 24-hour mode, this view will use the pattern
* returned by {@link #getFormat24Hour()}. In 12-hour mode, the pattern
* returned by {@link #getFormat12Hour()} is used instead.
- *
+ *
* If either one of the formats is null, the other format is used. If
* both formats are null, the default values {@link #DEFAULT_FORMAT_12_HOUR}
* and {@link #DEFAULT_FORMAT_24_HOUR} are used instead.
- *
+ *
* @return true if time should be displayed in 24-hour format, false if it
* should be displayed in 12-hour format.
- *
+ *
* @see #setFormat12Hour(CharSequence)
- * @see #getFormat12Hour()
+ * @see #getFormat12Hour()
* @see #setFormat24Hour(CharSequence)
- * @see #getFormat24Hour()
+ * @see #getFormat24Hour()
*/
public boolean is24HourModeEnabled() {
return DateFormat.is24HourFormat(getContext());
@@ -340,13 +351,13 @@ public class TextClock extends TextView {
/**
* Indicates which time zone is currently used by this view.
- *
+ *
* @return The ID of the current time zone or null if the default time zone,
* as set by the user, must be used
*
* @see TimeZone
* @see java.util.TimeZone#getAvailableIDs()
- * @see #setTimeZone(String)
+ * @see #setTimeZone(String)
*/
public String getTimeZone() {
return mTimeZone;
@@ -378,7 +389,7 @@ public class TextClock extends TextView {
/**
* Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
* depending on whether the user has selected 24-hour format.
- *
+ *
* Calling this method does not schedule or unschedule the time ticker.
*/
private void chooseFormat() {
@@ -388,17 +399,19 @@ public class TextClock extends TextView {
/**
* Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
* depending on whether the user has selected 24-hour format.
- *
+ *
* @param handleTicker true if calling this method should schedule/unschedule the
* time ticker, false otherwise
*/
private void chooseFormat(boolean handleTicker) {
final boolean format24Requested = is24HourModeEnabled();
+ LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
+
if (format24Requested) {
- mFormat = abc(mFormat24, mFormat12, DEFAULT_FORMAT_24_HOUR);
+ mFormat = abc(mFormat24, mFormat12, ld.timeFormat24);
} else {
- mFormat = abc(mFormat12, mFormat24, DEFAULT_FORMAT_12_HOUR);
+ mFormat = abc(mFormat12, mFormat24, ld.timeFormat12);
}
boolean hadSeconds = mHasSeconds;
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index eed3e67918e8..eb2d1fe3e79a 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -27,6 +27,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.SELinux;
import android.util.Log;
import com.android.org.bouncycastle.util.encoders.Base64;
@@ -64,6 +65,10 @@ public class LocalTransport extends IBackupTransport.Stub {
public LocalTransport(Context context) {
mContext = context;
+ mDataDir.mkdirs();
+ if (!SELinux.restorecon(mDataDir)) {
+ Log.e(TAG, "SELinux restorecon failed for " + mDataDir);
+ }
}
public Intent configurationIntent() {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 9b95be162361..d8f20c179dc0 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -11,10 +11,6 @@ else
LOCAL_CFLAGS += -DPACKED=""
endif
-ifneq ($(USE_CUSTOM_RUNTIME_HEAP_MAX),)
- LOCAL_CFLAGS += -DCUSTOM_RUNTIME_HEAP_MAX=$(USE_CUSTOM_RUNTIME_HEAP_MAX)
-endif
-
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER
endif
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index 42d408d23ce6..f5eaf94b15d2 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -2,16 +2,16 @@
**
** Copyright 2006, 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
+** 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
+** 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
+** 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.
*/
@@ -23,20 +23,17 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
+#include <utils/String8.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
-#if defined(__arm__)
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
- size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-
-extern "C" void free_malloc_leak_info(uint8_t* info);
-#endif
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+ size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-#define MAPS_FILE_SIZE 65 * 1024
+extern "C" void free_malloc_leak_info(uint8_t* info);
struct Header {
size_t mapSize;
@@ -48,96 +45,57 @@ struct Header {
namespace android {
+static void ReadFile(const char* path, String8& s) {
+ int fd = open(path, O_RDONLY);
+ if (fd != -1) {
+ char bytes[1024];
+ ssize_t byteCount;
+ while ((byteCount = TEMP_FAILURE_RETRY(read(fd, bytes, sizeof(bytes)))) > 0) {
+ s.append(bytes, byteCount);
+ }
+ close(fd);
+ }
+}
+
/*
- * Retrieve the native heap information and the info from /proc/<self>/maps,
+ * Retrieve the native heap information and the info from /proc/self/maps,
* copy them into a byte[] with a "struct Header" that holds data offsets,
* and return the array.
*/
-static jbyteArray getLeakInfo(JNIEnv *env, jobject clazz)
-{
-#if defined(__arm__)
- // get the info in /proc/[pid]/map
+static jbyteArray DdmHandleNativeHeap_getLeakInfo(JNIEnv* env, jobject) {
Header header;
memset(&header, 0, sizeof(header));
- pid_t pid = getpid();
-
- char path[FILENAME_MAX];
- sprintf(path, "/proc/%d/maps", pid);
-
- struct stat sb;
- int ret = stat(path, &sb);
-
- uint8_t* mapsFile = NULL;
- if (ret == 0) {
- mapsFile = (uint8_t*)malloc(MAPS_FILE_SIZE);
- int fd = open(path, O_RDONLY);
-
- if (mapsFile != NULL && fd != -1) {
- int amount = 0;
- do {
- uint8_t* ptr = mapsFile + header.mapSize;
- amount = read(fd, ptr, MAPS_FILE_SIZE);
- if (amount <= 0) {
- if (errno != EINTR)
- break;
- else
- continue;
- }
- header.mapSize += amount;
- } while (header.mapSize < MAPS_FILE_SIZE);
-
- ALOGD("**** read %d bytes from '%s'", (int) header.mapSize, path);
- }
- }
+ String8 maps;
+ ReadFile("/proc/self/maps", maps);
+ header.mapSize = maps.size();
uint8_t* allocBytes;
- get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize,
- &header.totalMemory, &header.backtraceSize);
+ get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize,
+ &header.totalMemory, &header.backtraceSize);
- jbyte* bytes = NULL;
- jbyte* ptr = NULL;
- jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
- if (array == NULL) {
- goto done;
- }
-
- bytes = env->GetByteArrayElements(array, NULL);
- ptr = bytes;
-
-// ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
-// header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
+ ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
+ header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
- memcpy(ptr, &header, sizeof(header));
- ptr += sizeof(header);
-
- if (header.mapSize > 0 && mapsFile != NULL) {
- memcpy(ptr, mapsFile, header.mapSize);
- ptr += header.mapSize;
+ jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
+ if (array != NULL) {
+ env->SetByteArrayRegion(array, 0,
+ sizeof(header), reinterpret_cast<jbyte*>(&header));
+ env->SetByteArrayRegion(array, sizeof(header),
+ maps.size(), reinterpret_cast<const jbyte*>(maps.string()));
+ env->SetByteArrayRegion(array, sizeof(header) + maps.size(),
+ header.allocSize, reinterpret_cast<jbyte*>(allocBytes));
}
-
- memcpy(ptr, allocBytes, header.allocSize);
- env->ReleaseByteArrayElements(array, bytes, 0);
-done:
- if (mapsFile != NULL) {
- free(mapsFile);
- }
- // free the info up!
free_malloc_leak_info(allocBytes);
-
return array;
-#else
- return NULL;
-#endif
}
static JNINativeMethod method_table[] = {
- { "getLeakInfo", "()[B", (void*)getLeakInfo },
+ { "getLeakInfo", "()[B", (void*) DdmHandleNativeHeap_getLeakInfo },
};
-int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env)
-{
+int register_android_ddm_DdmHandleNativeHeap(JNIEnv* env) {
return AndroidRuntime::registerNativeMethods(env, "android/ddm/DdmHandleNativeHeap", method_table, NELEM(method_table));
}
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 6e21a1123e7b..2883c102dada 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -43,6 +43,7 @@ enum {
HEAP_UNKNOWN,
HEAP_DALVIK,
HEAP_NATIVE,
+ HEAP_STACK,
HEAP_CURSOR,
HEAP_ASHMEM,
HEAP_UNKNOWN_DEV,
@@ -109,7 +110,7 @@ static jlong android_os_Debug_getNativeHeapAllocatedSize(JNIEnv *env, jobject cl
static jlong android_os_Debug_getNativeHeapFreeSize(JNIEnv *env, jobject clazz)
{
-#ifdef HAVE_MALLOC_H
+#ifdef HAVE_MALLOC_H
struct mallinfo info = mallinfo();
return (jlong) info.fordblks;
#else
@@ -164,6 +165,8 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
whichHeap = HEAP_NATIVE;
} else if (strstr(name, "/dev/ashmem/dalvik-") == name) {
whichHeap = HEAP_DALVIK;
+ } else if (strstr(name, "[stack") == name) {
+ whichHeap = HEAP_STACK;
} else if (strstr(name, "/dev/ashmem/CursorWindow") == name) {
whichHeap = HEAP_CURSOR;
} else if (strstr(name, "/dev/ashmem/") == name) {
@@ -191,7 +194,7 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
//ALOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
// isSqliteHeap, line);
-
+
while (true) {
if (fgets(line, 1024, fp) == 0) {
done = true;
@@ -233,7 +236,7 @@ static void load_maps(int pid, stats_t* stats)
{
char tmp[128];
FILE *fp;
-
+
sprintf(tmp, "/proc/%d/smaps", pid);
fp = fopen(tmp, "r");
if (fp == 0) return;
@@ -247,7 +250,7 @@ static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
{
stats_t stats[_NUM_HEAP];
memset(&stats, 0, sizeof(stats));
-
+
load_maps(pid, stats);
for (int i=_NUM_CORE_HEAP; i<_NUM_HEAP; i++) {
@@ -261,9 +264,9 @@ static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
env->SetIntField(object, stat_fields[i].privateDirty_field, stats[i].privateDirty);
env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
}
-
+
jintArray otherIntArray = (jintArray)env->GetObjectField(object, otherStats_field);
-
+
jint* otherArray = (jint*)env->GetPrimitiveArrayCritical(otherIntArray, 0);
if (otherArray == NULL) {
return;
@@ -328,7 +331,7 @@ static jint read_binder_stat(const char* stat)
char compare[128];
int len = snprintf(compare, 128, "proc %d", getpid());
-
+
// loop until we have the block that represents this process
do {
if (fgets(line, 1024, fp) == 0) {
@@ -336,15 +339,15 @@ static jint read_binder_stat(const char* stat)
}
} while (strncmp(compare, line, len));
- // now that we have this process, read until we find the stat that we are looking for
+ // now that we have this process, read until we find the stat that we are looking for
len = snprintf(compare, 128, " %s: ", stat);
-
+
do {
if (fgets(line, 1024, fp) == 0) {
return -1;
}
} while (strncmp(compare, line, len));
-
+
// we have the line, now increment the line ptr to the value
char* ptr = line + len;
return atoi(ptr);
@@ -510,7 +513,7 @@ static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject clazz,
jobject fileDescriptor)
{
if (fileDescriptor == NULL) {
- jniThrowNullPointerException(env, NULL);
+ jniThrowNullPointerException(env, "fd == null");
return;
}
int origFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
@@ -547,7 +550,7 @@ static void android_os_Debug_dumpNativeBacktraceToFile(JNIEnv* env, jobject claz
jint pid, jstring fileName)
{
if (fileName == NULL) {
- jniThrowNullPointerException(env, NULL);
+ jniThrowNullPointerException(env, "file == null");
return;
}
const jchar* str = env->GetStringCritical(fileName, 0);
@@ -611,6 +614,19 @@ int register_android_os_Debug(JNIEnv *env)
{
jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
+ // Sanity check the number of other statistics expected in Java matches here.
+ jfieldID numOtherStats_field = env->GetStaticFieldID(clazz, "NUM_OTHER_STATS", "I");
+ jint numOtherStats = env->GetStaticIntField(clazz, numOtherStats_field);
+ int expectedNumOtherStats = _NUM_HEAP - _NUM_CORE_HEAP;
+ if (numOtherStats != expectedNumOtherStats) {
+ jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+ "android.os.Debug.Meminfo.NUM_OTHER_STATS=%d expected %d",
+ numOtherStats, expectedNumOtherStats);
+ return JNI_ERR;
+ }
+
+ otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");
+
for (int i=0; i<_NUM_CORE_HEAP; i++) {
stat_fields[i].pss_field =
env->GetFieldID(clazz, stat_field_names[i].pss_name, "I");
@@ -620,8 +636,6 @@ int register_android_os_Debug(JNIEnv *env)
env->GetFieldID(clazz, stat_field_names[i].sharedDirty_name, "I");
}
- otherStats_field = env->GetFieldID(clazz, "otherStats", "[I");
-
return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index b12fdfc9999b..0a97f3922113 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -23,428 +23,407 @@
#include "selinux/selinux.h"
#include "selinux/android.h"
#include <errno.h>
+#include <ScopedLocalRef.h>
+#include <ScopedUtfChars.h>
+#include <UniquePtr.h>
namespace android {
- static jboolean isSELinuxDisabled = true;
-
- static void throw_NullPointerException(JNIEnv *env, const char* msg) {
- jclass clazz;
- clazz = env->FindClass("java/lang/NullPointerException");
- env->ThrowNew(clazz, msg);
- }
+struct SecurityContext_Delete {
+ void operator()(security_context_t p) const {
+ freecon(p);
+ }
+};
+typedef UniquePtr<char[], SecurityContext_Delete> Unique_SecurityContext;
- /*
- * Function: isSELinuxEnabled
- * Purpose: checks whether SELinux is enabled/disbaled
- * Parameters: none
- * Return value : true (enabled) or false (disabled)
- * Exceptions: none
- */
- static jboolean isSELinuxEnabled(JNIEnv *env, jobject classz) {
+static jboolean isSELinuxDisabled = true;
+/*
+ * Function: isSELinuxEnabled
+ * Purpose: checks whether SELinux is enabled/disbaled
+ * Parameters: none
+ * Return value : true (enabled) or false (disabled)
+ * Exceptions: none
+ */
+static jboolean isSELinuxEnabled(JNIEnv *env, jobject) {
return !isSELinuxDisabled;
- }
-
- /*
- * Function: isSELinuxEnforced
- * Purpose: return the current SELinux enforce mode
- * Parameters: none
- * Return value: true (enforcing) or false (permissive)
- * Exceptions: none
- */
- static jboolean isSELinuxEnforced(JNIEnv *env, jobject clazz) {
+}
+
+/*
+ * Function: isSELinuxEnforced
+ * Purpose: return the current SELinux enforce mode
+ * Parameters: none
+ * Return value: true (enforcing) or false (permissive)
+ * Exceptions: none
+ */
+static jboolean isSELinuxEnforced(JNIEnv *env, jobject) {
return (security_getenforce() == 1) ? true : false;
- }
+}
- /*
- * Function: setSELinuxEnforce
- * Purpose: set the SE Linux enforcing mode
- * Parameters: true (enforcing) or false (permissive)
- * Return value: true (success) or false (fail)
- * Exceptions: none
- */
- static jboolean setSELinuxEnforce(JNIEnv *env, jobject clazz, jboolean value) {
- if (isSELinuxDisabled)
- return false;
+/*
+ * Function: setSELinuxEnforce
+ * Purpose: set the SE Linux enforcing mode
+ * Parameters: true (enforcing) or false (permissive)
+ * Return value: true (success) or false (fail)
+ * Exceptions: none
+ */
+static jboolean setSELinuxEnforce(JNIEnv *env, jobject, jboolean value) {
+ if (isSELinuxDisabled) {
+ return false;
+ }
- int enforce = (value) ? 1 : 0;
+ int enforce = value ? 1 : 0;
return (security_setenforce(enforce) != -1) ? true : false;
- }
-
- /*
- * Function: getPeerCon
- * Purpose: retrieves security context of peer socket
- * Parameters:
- * fileDescriptor: peer socket file as a FileDescriptor object
- * Returns: jstring representing the security_context of socket or NULL if error
- * Exceptions: NullPointerException if fileDescriptor object is NULL
- */
- static jstring getPeerCon(JNIEnv *env, jobject clazz, jobject fileDescriptor) {
- if (isSELinuxDisabled)
- return NULL;
+}
- if (fileDescriptor == NULL) {
- throw_NullPointerException(env, "Trying to check security context of a null peer socket.");
- return NULL;
+/*
+ * Function: getPeerCon
+ * Purpose: retrieves security context of peer socket
+ * Parameters:
+ * fileDescriptor: peer socket file as a FileDescriptor object
+ * Returns: jstring representing the security_context of socket or NULL if error
+ * Exceptions: NullPointerException if fileDescriptor object is NULL
+ */
+static jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) {
+ if (isSELinuxDisabled) {
+ return NULL;
}
- security_context_t context = NULL;
- jstring securityString = NULL;
+ if (fileDescriptor == NULL) {
+ jniThrowNullPointerException(env,
+ "Trying to check security context of a null peer socket.");
+ return NULL;
+ }
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
if (env->ExceptionOccurred() != NULL) {
- ALOGE("There was an issue with retrieving the file descriptor");
- goto bail;
+ ALOGE("getPeerCon => getFD for %p failed", fileDescriptor);
+ return NULL;
}
- if (getpeercon(fd, &context) == -1)
- goto bail;
-
- ALOGV("getPeerCon: Successfully retrived context of peer socket '%s'", context);
+ security_context_t tmp;
+ int ret = getpeercon(fd, &tmp);
+ Unique_SecurityContext context(tmp);
- securityString = env->NewStringUTF(context);
-
- bail:
- if (context != NULL)
- freecon(context);
-
- return securityString;
- }
-
- /*
- * Function: setFSCreateCon
- * Purpose: set security context used for creating a new file system object
- * Parameters:
- * context: security_context_t representing the new context of a file system object,
- * set to NULL to return to the default policy behavior
- * Returns: true on success, false on error
- * Exception: none
- */
- static jboolean setFSCreateCon(JNIEnv *env, jobject clazz, jstring context) {
- if (isSELinuxDisabled)
- return false;
-
- char * securityContext = NULL;
- const char *constant_securityContext = NULL;
+ ScopedLocalRef<jstring> contextStr(env, NULL);
+ if (ret != -1) {
+ contextStr.reset(env->NewStringUTF(context.get()));
+ }
- if (context != NULL) {
- constant_securityContext = env->GetStringUTFChars(context, NULL);
+ ALOGV("getPeerCon(%d) => %s", fd, contextStr.get());
+ return contextStr.release();
+}
- // GetStringUTFChars returns const char * yet setfscreatecon needs char *
- securityContext = const_cast<char *>(constant_securityContext);
+/*
+ * Function: setFSCreateCon
+ * Purpose: set security context used for creating a new file system object
+ * Parameters:
+ * context: security_context_t representing the new context of a file system object,
+ * set to NULL to return to the default policy behavior
+ * Returns: true on success, false on error
+ * Exception: none
+ */
+static jboolean setFSCreateCon(JNIEnv *env, jobject, jstring contextStr) {
+ if (isSELinuxDisabled) {
+ return false;
}
- int ret;
- if ((ret = setfscreatecon(securityContext)) == -1)
- goto bail;
+ UniquePtr<ScopedUtfChars> context;
+ const char* context_c_str = NULL;
+ if (contextStr != NULL) {
+ context.reset(new ScopedUtfChars(env, contextStr));
+ context_c_str = context->c_str();
+ if (context_c_str == NULL) {
+ return false;
+ }
+ }
- ALOGV("setFSCreateCon: set new security context to '%s' ", context == NULL ? "default", context);
+ int ret = setfscreatecon(const_cast<char *>(context_c_str));
- bail:
- if (constant_securityContext != NULL)
- env->ReleaseStringUTFChars(context, constant_securityContext);
+ ALOGV("setFSCreateCon(%s) => %d", context_c_str, ret);
return (ret == 0) ? true : false;
- }
-
- /*
- * Function: setFileCon
- * Purpose: set the security context of a file object
- * Parameters:
- * path: the location of the file system object
- * con: the new security context of the file system object
- * Returns: true on success, false on error
- * Exception: NullPointerException is thrown if either path or context strign are NULL
- */
- static jboolean setFileCon(JNIEnv *env, jobject clazz, jstring path, jstring con) {
- if (isSELinuxDisabled)
- return false;
+}
- if (path == NULL) {
- throw_NullPointerException(env, "Trying to change the security context of a NULL file object.");
- return false;
+/*
+ * Function: setFileCon
+ * Purpose: set the security context of a file object
+ * Parameters:
+ * path: the location of the file system object
+ * context: the new security context of the file system object
+ * Returns: true on success, false on error
+ * Exception: NullPointerException is thrown if either path or context strign are NULL
+ */
+static jboolean setFileCon(JNIEnv *env, jobject, jstring pathStr, jstring contextStr) {
+ if (isSELinuxDisabled) {
+ return false;
}
- if (con == NULL) {
- throw_NullPointerException(env, "Trying to set the security context of a file object with NULL.");
- return false;
+ ScopedUtfChars path(env, pathStr);
+ if (path.c_str() == NULL) {
+ return false;
}
- const char *objectPath = env->GetStringUTFChars(path, NULL);
- const char *constant_con = env->GetStringUTFChars(con, NULL);
+ ScopedUtfChars context(env, contextStr);
+ if (context.c_str() == NULL) {
+ return false;
+ }
// GetStringUTFChars returns const char * yet setfilecon needs char *
- char *newCon = const_cast<char *>(constant_con);
-
- int ret;
- if ((ret = setfilecon(objectPath, newCon)) == -1)
- goto bail;
-
- ALOGV("setFileCon: Succesfully set security context '%s' for '%s'", newCon, objectPath);
+ char *tmp = const_cast<char *>(context.c_str());
+ int ret = setfilecon(path.c_str(), tmp);
- bail:
- env->ReleaseStringUTFChars(path, objectPath);
- env->ReleaseStringUTFChars(con, constant_con);
+ ALOGV("setFileCon(%s, %s) => %d", path.c_str(), context.c_str(), ret);
return (ret == 0) ? true : false;
- }
-
- /*
- * Function: getFileCon
- * Purpose: retrieves the context associated with the given path in the file system
- * Parameters:
- * path: given path in the file system
- * Returns:
- * string representing the security context string of the file object
- * the string may be NULL if an error occured
- * Exceptions: NullPointerException if the path object is null
- */
- static jstring getFileCon(JNIEnv *env, jobject clazz, jstring path) {
- if (isSELinuxDisabled)
- return NULL;
+}
- if (path == NULL) {
- throw_NullPointerException(env, "Trying to check security context of a null path.");
- return NULL;
+/*
+ * Function: getFileCon
+ * Purpose: retrieves the context associated with the given path in the file system
+ * Parameters:
+ * path: given path in the file system
+ * Returns:
+ * string representing the security context string of the file object
+ * the string may be NULL if an error occured
+ * Exceptions: NullPointerException if the path object is null
+ */
+static jstring getFileCon(JNIEnv *env, jobject, jstring pathStr) {
+ if (isSELinuxDisabled) {
+ return NULL;
}
- const char *objectPath = env->GetStringUTFChars(path, NULL);
-
- security_context_t context = NULL;
- jstring securityString = NULL;
+ ScopedUtfChars path(env, pathStr);
+ if (path.c_str() == NULL) {
+ return NULL;
+ }
- if (getfilecon(objectPath, &context) == -1)
- goto bail;
+ security_context_t tmp;
+ int ret = getfilecon(path.c_str(), &tmp);
+ Unique_SecurityContext context(tmp);
- ALOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath);
+ ScopedLocalRef<jstring> securityString(env, NULL);
+ if (ret != -1) {
+ securityString.reset(env->NewStringUTF(context.get()));
+ }
- securityString = env->NewStringUTF(context);
+ ALOGV("getFileCon(%s) => %s", path.c_str(), context.get());
+ return securityString.release();
+}
- bail:
- if (context != NULL)
- freecon(context);
+/*
+ * Function: getCon
+ * Purpose: Get the context of the current process.
+ * Parameters: none
+ * Returns: a jstring representing the security context of the process,
+ * the jstring may be NULL if there was an error
+ * Exceptions: none
+ */
+static jstring getCon(JNIEnv *env, jobject) {
+ if (isSELinuxDisabled) {
+ return NULL;
+ }
- env->ReleaseStringUTFChars(path, objectPath);
+ security_context_t tmp;
+ int ret = getcon(&tmp);
+ Unique_SecurityContext context(tmp);
- return securityString;
- }
+ ScopedLocalRef<jstring> securityString(env, NULL);
+ if (ret != -1) {
+ securityString.reset(env->NewStringUTF(context.get()));
+ }
- /*
- * Function: getCon
- * Purpose: Get the context of the current process.
- * Parameters: none
- * Returns: a jstring representing the security context of the process,
- * the jstring may be NULL if there was an error
- * Exceptions: none
- */
- static jstring getCon(JNIEnv *env, jobject clazz) {
- if (isSELinuxDisabled)
- return NULL;
+ ALOGV("getCon() => %s", context.get());
+ return securityString.release();
+}
- security_context_t context = NULL;
- jstring securityString = NULL;
+/*
+ * Function: getPidCon
+ * Purpose: Get the context of a process identified by its pid
+ * Parameters:
+ * pid: a jint representing the process
+ * Returns: a jstring representing the security context of the pid,
+ * the jstring may be NULL if there was an error
+ * Exceptions: none
+ */
+static jstring getPidCon(JNIEnv *env, jobject, jint pid) {
+ if (isSELinuxDisabled) {
+ return NULL;
+ }
- if (getcon(&context) == -1)
- goto bail;
+ security_context_t tmp;
+ int ret = getpidcon(static_cast<pid_t>(pid), &tmp);
+ Unique_SecurityContext context(tmp);
- ALOGV("getCon: Successfully retrieved context '%s'", context);
+ ScopedLocalRef<jstring> securityString(env, NULL);
+ if (ret != -1) {
+ securityString.reset(env->NewStringUTF(context.get()));
+ }
- securityString = env->NewStringUTF(context);
+ ALOGV("getPidCon(%d) => %s", pid, context.get());
+ return securityString.release();
+}
- bail:
- if (context != NULL)
- freecon(context);
+/*
+ * Function: getBooleanNames
+ * Purpose: Gets a list of the SELinux boolean names.
+ * Parameters: None
+ * Returns: an array of strings containing the SELinux boolean names.
+ * returns NULL string on error
+ * Exceptions: None
+ */
+static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv) {
+ if (isSELinuxDisabled) {
+ return NULL;
+ }
- return securityString;
- }
+ char **list;
+ int len;
+ if (security_get_boolean_names(&list, &len) == -1) {
+ return NULL;
+ }
- /*
- * Function: getPidCon
- * Purpose: Get the context of a process identified by its pid
- * Parameters:
- * pid: a jint representing the process
- * Returns: a jstring representing the security context of the pid,
- * the jstring may be NULL if there was an error
- * Exceptions: none
- */
- static jstring getPidCon(JNIEnv *env, jobject clazz, jint pid) {
- if (isSELinuxDisabled)
- return NULL;
+ jclass stringClass = env->FindClass("java/lang/String");
+ jobjectArray stringArray = env->NewObjectArray(len, stringClass, NULL);
+ for (int i = 0; i < len; i++) {
+ ScopedLocalRef<jstring> obj(env, env->NewStringUTF(list[i]));
+ env->SetObjectArrayElement(stringArray, i, obj.get());
+ free(list[i]);
+ }
+ free(list);
- security_context_t context = NULL;
- jstring securityString = NULL;
+ return stringArray;
+}
- pid_t checkPid = (pid_t)pid;
+/*
+ * Function: getBooleanValue
+ * Purpose: Gets the value for the given SELinux boolean name.
+ * Parameters:
+ * String: The name of the SELinux boolean.
+ * Returns: a boolean: (true) boolean is set or (false) it is not.
+ * Exceptions: None
+ */
+static jboolean getBooleanValue(JNIEnv *env, jobject, jstring nameStr) {
+ if (isSELinuxDisabled) {
+ return false;
+ }
- if (getpidcon(checkPid, &context) == -1)
- goto bail;
+ if (nameStr == NULL) {
+ return false;
+ }
- ALOGV("getPidCon: Successfully retrived context '%s' for pid '%d'", context, checkPid);
+ ScopedUtfChars name(env, nameStr);
+ int ret = security_get_boolean_active(name.c_str());
- securityString = env->NewStringUTF(context);
+ ALOGV("getBooleanValue(%s) => %d", name.c_str(), ret);
+ return (ret == 1) ? true : false;
+}
- bail:
- if (context != NULL)
- freecon(context);
+/*
+ * Function: setBooleanNames
+ * Purpose: Sets the value for the given SELinux boolean name.
+ * Parameters:
+ * String: The name of the SELinux boolean.
+ * Boolean: The new value of the SELinux boolean.
+ * Returns: a boolean indicating whether or not the operation succeeded.
+ * Exceptions: None
+ */
+static jboolean setBooleanValue(JNIEnv *env, jobject, jstring nameStr, jboolean value) {
+ if (isSELinuxDisabled) {
+ return false;
+ }
- return securityString;
- }
-
- /*
- * Function: getBooleanNames
- * Purpose: Gets a list of the SELinux boolean names.
- * Parameters: None
- * Returns: an array of strings containing the SELinux boolean names.
- * returns NULL string on error
- * Exceptions: None
- */
- static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv clazz) {
- if (isSELinuxDisabled)
- return NULL;
+ if (nameStr == NULL) {
+ return false;
+ }
- char **list;
- int i, len, ret;
- jclass stringClass;
- jobjectArray stringArray = NULL;
-
- if (security_get_boolean_names(&list, &len) == -1)
- return NULL;
-
- stringClass = env->FindClass("java/lang/String");
- stringArray = env->NewObjectArray(len, stringClass, env->NewStringUTF(""));
- for (i = 0; i < len; i++) {
- jstring obj;
- obj = env->NewStringUTF(list[i]);
- env->SetObjectArrayElement(stringArray, i, obj);
- env->DeleteLocalRef(obj);
- free(list[i]);
+ ScopedUtfChars name(env, nameStr);
+ int ret = security_set_boolean(name.c_str(), value ? 1 : 0);
+ if (ret) {
+ return false;
}
- free(list);
- return stringArray;
- }
-
- /*
- * Function: getBooleanValue
- * Purpose: Gets the value for the given SELinux boolean name.
- * Parameters:
- * String: The name of the SELinux boolean.
- * Returns: a boolean: (true) boolean is set or (false) it is not.
- * Exceptions: None
- */
- static jboolean getBooleanValue(JNIEnv *env, jobject clazz, jstring name) {
- if (isSELinuxDisabled)
- return false;
-
- const char *boolean_name;
- int ret;
-
- if (name == NULL)
- return false;
- boolean_name = env->GetStringUTFChars(name, NULL);
- ret = security_get_boolean_active(boolean_name);
- env->ReleaseStringUTFChars(name, boolean_name);
- return (ret == 1) ? true : false;
- }
-
- /*
- * Function: setBooleanNames
- * Purpose: Sets the value for the given SELinux boolean name.
- * Parameters:
- * String: The name of the SELinux boolean.
- * Boolean: The new value of the SELinux boolean.
- * Returns: a boolean indicating whether or not the operation succeeded.
- * Exceptions: None
- */
- static jboolean setBooleanValue(JNIEnv *env, jobject clazz, jstring name, jboolean value) {
- if (isSELinuxDisabled)
- return false;
-
- const char *boolean_name = NULL;
- int ret;
-
- if (name == NULL)
- return false;
- boolean_name = env->GetStringUTFChars(name, NULL);
- ret = security_set_boolean(boolean_name, (value) ? 1 : 0);
- env->ReleaseStringUTFChars(name, boolean_name);
- if (ret)
- return false;
-
- if (security_commit_booleans() == -1)
- return false;
+ if (security_commit_booleans() == -1) {
+ return false;
+ }
return true;
- }
+}
- /*
- * Function: checkSELinuxAccess
- * Purpose: Check permissions between two security contexts.
- * Parameters: scon: subject security context as a string
- * tcon: object security context as a string
- * tclass: object's security class name as a string
- * perm: permission name as a string
- * Returns: boolean: (true) if permission was granted, (false) otherwise
- * Exceptions: None
- */
- static jboolean checkSELinuxAccess(JNIEnv *env, jobject clazz, jstring scon, jstring tcon, jstring tclass, jstring perm) {
- if (isSELinuxDisabled)
- return true;
+/*
+ * Function: checkSELinuxAccess
+ * Purpose: Check permissions between two security contexts.
+ * Parameters: subjectContextStr: subject security context as a string
+ * objectContextStr: object security context as a string
+ * objectClassStr: object's security class name as a string
+ * permissionStr: permission name as a string
+ * Returns: boolean: (true) if permission was granted, (false) otherwise
+ * Exceptions: None
+ */
+static jboolean checkSELinuxAccess(JNIEnv *env, jobject, jstring subjectContextStr,
+ jstring objectContextStr, jstring objectClassStr, jstring permissionStr) {
+ if (isSELinuxDisabled) {
+ return true;
+ }
- int accessGranted = -1;
+ ScopedUtfChars subjectContext(env, subjectContextStr);
+ if (subjectContext.c_str() == NULL) {
+ return false;
+ }
- const char *const_scon, *const_tcon, *mytclass, *myperm;
- char *myscon, *mytcon;
+ ScopedUtfChars objectContext(env, objectContextStr);
+ if (objectContext.c_str() == NULL) {
+ return false;
+ }
- if (scon == NULL || tcon == NULL || tclass == NULL || perm == NULL)
- goto bail;
+ ScopedUtfChars objectClass(env, objectClassStr);
+ if (objectClass.c_str() == NULL) {
+ return false;
+ }
- const_scon = env->GetStringUTFChars(scon, NULL);
- const_tcon = env->GetStringUTFChars(tcon, NULL);
- mytclass = env->GetStringUTFChars(tclass, NULL);
- myperm = env->GetStringUTFChars(perm, NULL);
+ ScopedUtfChars permission(env, permissionStr);
+ if (permission.c_str() == NULL) {
+ return false;
+ }
- // selinux_check_access needs char* for some
- myscon = const_cast<char *>(const_scon);
- mytcon = const_cast<char *>(const_tcon);
+ char *tmp1 = const_cast<char *>(subjectContext.c_str());
+ char *tmp2 = const_cast<char *>(objectContext.c_str());
+ int accessGranted = selinux_check_access(tmp1, tmp2, objectClass.c_str(), permission.c_str(),
+ NULL);
- accessGranted = selinux_check_access(myscon, mytcon, mytclass, myperm, NULL);
+ ALOGV("checkSELinuxAccess(%s, %s, %s, %s) => %d", subjectContext.c_str(), objectContext.c_str(),
+ objectClass.c_str(), permission.c_str(), accessGranted);
- ALOGV("selinux_check_access returned %d", accessGranted);
+ return (accessGranted == 0) ? true : false;
+}
- env->ReleaseStringUTFChars(scon, const_scon);
- env->ReleaseStringUTFChars(tcon, const_tcon);
- env->ReleaseStringUTFChars(tclass, mytclass);
- env->ReleaseStringUTFChars(perm, myperm);
+/*
+ * Function: native_restorecon
+ * Purpose: restore default SELinux security context
+ * Parameters: pathname: the pathname for the file to be relabeled
+ * Returns: boolean: (true) file label successfully restored, (false) otherwise
+ * Exceptions: none
+ */
+static jboolean native_restorecon(JNIEnv *env, jobject, jstring pathnameStr) {
+ if (isSELinuxDisabled) {
+ return true;
+ }
- bail:
- return (accessGranted == 0) ? true : false;
- }
-
- /*
- * Function: native_restorecon
- * Purpose: restore default SELinux security context
- * Parameters: pathname: the pathname for the file to be relabeled
- * Returns: boolean: (true) file label successfully restored, (false) otherwise
- * Exceptions: none
- */
- static jboolean native_restorecon(JNIEnv *env, jobject clazz, jstring pathname) {
- if (isSELinuxDisabled)
- return true;
-
- const char *file = const_cast<char *>(env->GetStringUTFChars(pathname, NULL));
- int ret = selinux_android_restorecon(file);
- env->ReleaseStringUTFChars(pathname, file);
- return (ret == 0);
- }
+ ScopedUtfChars pathname(env, pathnameStr);
+ if (pathname.c_str() == NULL) {
+ ALOGV("restorecon(%p) => threw exception", pathname);
+ return false;
+ }
- /*
- * JNI registration.
- */
- static JNINativeMethod method_table[] = {
+ int ret = selinux_android_restorecon(pathname.c_str());
+ ALOGV("restorecon(%s) => %d", pathname.c_str(), ret);
+ return (ret == 0);
+}
+/*
+ * JNI registration.
+ */
+static JNINativeMethod method_table[] = {
/* name, signature, funcPtr */
{ "checkSELinuxAccess" , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess },
{ "getBooleanNames" , "()[Ljava/lang/String;" , (void*)getBooleanNames },
@@ -460,25 +439,25 @@ namespace android {
{ "setFileContext" , "(Ljava/lang/String;Ljava/lang/String;)Z" , (void*)setFileCon },
{ "setFSCreateContext" , "(Ljava/lang/String;)Z" , (void*)setFSCreateCon },
{ "setSELinuxEnforce" , "(Z)Z" , (void*)setSELinuxEnforce},
- };
+};
- static int log_callback(int type, const char *fmt, ...) {
+static int log_callback(int type, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
LOG_PRI_VA(ANDROID_LOG_ERROR, "SELinux", fmt, ap);
va_end(ap);
return 0;
- }
+}
- int register_android_os_SELinux(JNIEnv *env) {
+int register_android_os_SELinux(JNIEnv *env) {
union selinux_callback cb;
cb.func_log = log_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
isSELinuxDisabled = (is_selinux_enabled() != 1) ? true : false;
- return AndroidRuntime::registerNativeMethods(
- env, "android/os/SELinux",
- method_table, NELEM(method_table));
- }
+ return AndroidRuntime::registerNativeMethods(env, "android/os/SELinux", method_table,
+ NELEM(method_table));
+}
+
}
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index 7e5dedecbdc6..83d6df171a54 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -27,12 +27,8 @@
#include <JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"
-#include <linux/capability.h>
-#include <linux/prctl.h>
+#include <sys/capability.h>
#include <sys/prctl.h>
-extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
-extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
-
namespace android {
diff --git a/core/res/res/values-mcc286/config.xml b/core/res/res/values-mcc286/config.xml
index d99d0516eb21..d99d0516eb21 100755..100644
--- a/core/res/res/values-mcc286/config.xml
+++ b/core/res/res/values-mcc286/config.xml
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8e66a77606b0..cc6131c5c7fa 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3050,12 +3050,12 @@
<!-- Specifies the formatting pattern used to show the time and/or date
in 12-hour mode. Please refer to {@link android.text.format.DateFormat}
for a complete description of accepted formatting patterns.
- The default pattern is "h:mm aa". -->
+ The default pattern is a locale-appropriate equivalent of "h:mm a". -->
<attr name="format12Hour" format="string"/>
<!-- Specifies the formatting pattern used to show the time and/or date
in 24-hour mode. Please refer to {@link android.text.format.DateFormat}
for a complete description of accepted formatting patterns.
- The default pattern is "k:mm". -->
+ The default pattern is a locale-appropriate equivalent of "H:mm". -->
<attr name="format24Hour" format="string"/>
<!-- Specifies the time zone to use. When this attribute is specified, the
TextClock will ignore the time zone of the system. To use the user's
diff --git a/core/res/res/xml/apns.xml b/core/res/res/xml/apns.xml
index 8c7245c5d01b..249b598a4653 100644
--- a/core/res/res/xml/apns.xml
+++ b/core/res/res/xml/apns.xml
@@ -20,6 +20,6 @@
<!-- If you edit this version, also edit the version in the partner-supplied
apns-conf.xml configuration file -->
-<apns version="7">
+<apns version="8">
</apns>
diff --git a/core/res/res/xml/kg_password_kbd_numeric.xml b/core/res/res/xml/kg_password_kbd_numeric.xml
index 93b32af2de92..93b32af2de92 100755..100644
--- a/core/res/res/xml/kg_password_kbd_numeric.xml
+++ b/core/res/res/xml/kg_password_kbd_numeric.xml
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
index cf42bb1c003a..c5f6236fe153 100644
--- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -21,8 +21,9 @@ import android.test.suitebuilder.annotation.SmallTest;
import junit.framework.TestCase;
public class DateUtilsTest extends TestCase {
+ // This test is not in CTS because formatDuration is @hidden.
@SmallTest
- public void testFormatDurationSeconds() throws Exception {
+ public void test_formatDuration_seconds() throws Exception {
assertEquals("0 seconds", DateUtils.formatDuration(0));
assertEquals("0 seconds", DateUtils.formatDuration(1));
assertEquals("0 seconds", DateUtils.formatDuration(499));
@@ -31,16 +32,18 @@ public class DateUtilsTest extends TestCase {
assertEquals("2 seconds", DateUtils.formatDuration(1500));
}
+ // This test is not in CTS because formatDuration is @hidden.
@SmallTest
- public void testFormatDurationMinutes() throws Exception {
+ public void test_formatDuration_Minutes() throws Exception {
assertEquals("59 seconds", DateUtils.formatDuration(59000));
assertEquals("60 seconds", DateUtils.formatDuration(59500));
assertEquals("1 minute", DateUtils.formatDuration(60000));
assertEquals("2 minutes", DateUtils.formatDuration(120000));
}
+ // This test is not in CTS because formatDuration is @hidden.
@SmallTest
- public void testFormatDurationHours() throws Exception {
+ public void test_formatDuration_Hours() throws Exception {
assertEquals("59 minutes", DateUtils.formatDuration(3540000));
assertEquals("1 hour", DateUtils.formatDuration(3600000));
assertEquals("48 hours", DateUtils.formatDuration(172800000));
diff --git a/core/tests/coretests/src/android/webkit/WebkitTest.java b/core/tests/coretests/src/android/webkit/WebkitTest.java
index 17b4088f0996..4685e3cf08d7 100644
--- a/core/tests/coretests/src/android/webkit/WebkitTest.java
+++ b/core/tests/coretests/src/android/webkit/WebkitTest.java
@@ -52,7 +52,7 @@ public class WebkitTest extends AndroidTestCase {
date.setTime(time);
c.setTime(date);
index = dateSorter.getIndex(time);
- Log.i(LOGTAG, "time: " + DateFormat.format("yyyy/MM/dd kk:mm:ss", c).toString() +
+ Log.i(LOGTAG, "time: " + DateFormat.format("yyyy/MM/dd HH:mm:ss", c).toString() +
" " + index + " " + dateSorter.getLabel(index));
}
}
diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk
index b40e38552920..b40e38552920 100755..100644
--- a/data/sounds/AudioPackage10.mk
+++ b/data/sounds/AudioPackage10.mk
diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk
index 93c43da5d075..93c43da5d075 100755..100644
--- a/data/sounds/AudioPackage8.mk
+++ b/data/sounds/AudioPackage8.mk
diff --git a/data/sounds/AudioPackage9.mk b/data/sounds/AudioPackage9.mk
index 73e4fd31d971..73e4fd31d971 100755..100644
--- a/data/sounds/AudioPackage9.mk
+++ b/data/sounds/AudioPackage9.mk
diff --git a/data/sounds/alarms/ogg/Krypton.ogg b/data/sounds/alarms/ogg/Krypton.ogg
index 48f956bc1b7a..48f956bc1b7a 100755..100644
--- a/data/sounds/alarms/ogg/Krypton.ogg
+++ b/data/sounds/alarms/ogg/Krypton.ogg
Binary files differ
diff --git a/data/sounds/alarms/wav/Argon.wav b/data/sounds/alarms/wav/Argon.wav
index 56e57fc0e2ba..56e57fc0e2ba 100755..100644
--- a/data/sounds/alarms/wav/Argon.wav
+++ b/data/sounds/alarms/wav/Argon.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Carbon.wav b/data/sounds/alarms/wav/Carbon.wav
index 2b855e1b5777..2b855e1b5777 100755..100644
--- a/data/sounds/alarms/wav/Carbon.wav
+++ b/data/sounds/alarms/wav/Carbon.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Osmium.wav b/data/sounds/alarms/wav/Osmium.wav
index 2dcc47f8c75f..2dcc47f8c75f 100755..100644
--- a/data/sounds/alarms/wav/Osmium.wav
+++ b/data/sounds/alarms/wav/Osmium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Platinum.wav b/data/sounds/alarms/wav/Platinum.wav
index 08ea03e2b6f7..08ea03e2b6f7 100755..100644
--- a/data/sounds/alarms/wav/Platinum.wav
+++ b/data/sounds/alarms/wav/Platinum.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Promethium.wav b/data/sounds/alarms/wav/Promethium.wav
index 08ea03e2b6f7..08ea03e2b6f7 100755..100644
--- a/data/sounds/alarms/wav/Promethium.wav
+++ b/data/sounds/alarms/wav/Promethium.wav
Binary files differ
diff --git a/docs/html/google/play/billing/v2/billing_integrate.jd b/docs/html/google/play/billing/v2/billing_integrate.jd
index 7b748a399b66..7b748a399b66 100755..100644
--- a/docs/html/google/play/billing/v2/billing_integrate.jd
+++ b/docs/html/google/play/billing/v2/billing_integrate.jd
diff --git a/docs/html/images/ui/notifications/custom_message.png b/docs/html/images/ui/notifications/custom_message.png
index 00b763239c40..00b763239c40 100755..100644
--- a/docs/html/images/ui/notifications/custom_message.png
+++ b/docs/html/images/ui/notifications/custom_message.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/notifications_window.png b/docs/html/images/ui/notifications/notifications_window.png
index 0354ee92bda4..0354ee92bda4 100755..100644
--- a/docs/html/images/ui/notifications/notifications_window.png
+++ b/docs/html/images/ui/notifications/notifications_window.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/status_bar.png b/docs/html/images/ui/notifications/status_bar.png
index f0240a5f0b52..f0240a5f0b52 100755..100644
--- a/docs/html/images/ui/notifications/status_bar.png
+++ b/docs/html/images/ui/notifications/status_bar.png
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.mp4 b/docs/html/training/animation/anim_card_flip.mp4
index e885f987c413..e885f987c413 100755..100644
--- a/docs/html/training/animation/anim_card_flip.mp4
+++ b/docs/html/training/animation/anim_card_flip.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.ogv b/docs/html/training/animation/anim_card_flip.ogv
index 33cd86c23e09..33cd86c23e09 100755..100644
--- a/docs/html/training/animation/anim_card_flip.ogv
+++ b/docs/html/training/animation/anim_card_flip.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_card_flip.webm b/docs/html/training/animation/anim_card_flip.webm
index a670d7831c8a..a670d7831c8a 100755..100644
--- a/docs/html/training/animation/anim_card_flip.webm
+++ b/docs/html/training/animation/anim_card_flip.webm
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.mp4 b/docs/html/training/animation/anim_screenslide.mp4
index 3e6502642e64..3e6502642e64 100755..100644
--- a/docs/html/training/animation/anim_screenslide.mp4
+++ b/docs/html/training/animation/anim_screenslide.mp4
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.ogv b/docs/html/training/animation/anim_screenslide.ogv
index c45ebd44db53..c45ebd44db53 100755..100644
--- a/docs/html/training/animation/anim_screenslide.ogv
+++ b/docs/html/training/animation/anim_screenslide.ogv
Binary files differ
diff --git a/docs/html/training/animation/anim_screenslide.webm b/docs/html/training/animation/anim_screenslide.webm
index c72adbcb1384..c72adbcb1384 100755..100644
--- a/docs/html/training/animation/anim_screenslide.webm
+++ b/docs/html/training/animation/anim_screenslide.webm
Binary files differ
diff --git a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
index 79a763024c93..83faf356f2d5 100644
--- a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
@@ -28,10 +28,28 @@ import java.util.Date;
import javax.security.auth.x500.X500Principal;
/**
- * This provides the required parameters needed for initializing the KeyPair
- * generator that works with
- * <a href="{@docRoot}guide/topics/security/keystore.html">Android KeyStore
- * facility</a>.
+ * This provides the required parameters needed for initializing the
+ * {@code KeyPairGenerator} that works with <a href="{@docRoot}
+ * guide/topics/security/keystore.html">Android KeyStore facility</a>. The
+ * Android KeyStore facility is accessed through a
+ * {@link java.security.KeyPairGenerator} API using the
+ * {@code AndroidKeyPairGenerator} provider. The {@code context} passed in may
+ * be used to pop up some UI to ask the user to unlock or initialize the Android
+ * keystore facility.
+ * <p>
+ * After generation, the {@code keyStoreAlias} is used with the
+ * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter)}
+ * interface to retrieve the {@link PrivateKey} and its associated
+ * {@link Certificate} chain.
+ * <p>
+ * The KeyPair generator will create a self-signed certificate with the subject
+ * as its X.509v3 Subject Distinguished Name and as its X.509v3 Issuer
+ * Distinguished Name along with the other parameters specified with the
+ * {@link Builder}.
+ * <p>
+ * The self-signed certificate may be replaced at a later time by a certificate
+ * signed by a real Certificate Authority.
+ *
* @hide
*/
public class AndroidKeyPairGeneratorSpec implements AlgorithmParameterSpec {
@@ -74,6 +92,7 @@ public class AndroidKeyPairGeneratorSpec implements AlgorithmParameterSpec {
* period
* @throws IllegalArgumentException when any argument is {@code null} or
* {@code endDate} is before {@code startDate}.
+ * @hide should be built with AndroidKeyPairGeneratorSpecBuilder
*/
public AndroidKeyPairGeneratorSpec(Context context, String keyStoreAlias,
X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate) {
@@ -142,4 +161,121 @@ public class AndroidKeyPairGeneratorSpec implements AlgorithmParameterSpec {
Date getEndDate() {
return mEndDate;
}
+
+ /**
+ * Builder class for {@link AndroidKeyPairGeneratorSpec} objects.
+ * <p>
+ * This will build a parameter spec for use with the <a href="{@docRoot}
+ * guide/topics/security/keystore.html">Android KeyStore facility</a>.
+ * <p>
+ * The required fields must be filled in with the builder.
+ * <p>
+ * Example:
+ *
+ * <pre class="prettyprint">
+ * Calendar start = new Calendar();
+ * Calendar end = new Calendar();
+ * end.add(1, Calendar.YEAR);
+ *
+ * AndroidKeyPairGeneratorSpec spec = new AndroidKeyPairGeneratorSpec.Builder(mContext)
+ * .setAlias("myKey")
+ * .setSubject(new X500Principal("CN=myKey"))
+ * .setSerial(BigInteger.valueOf(1337))
+ * .setStartDate(start.getTime())
+ * .setEndDate(end.getTime())
+ * .build();
+ * </pre>
+ */
+ public static class Builder {
+ private final Context mContext;
+
+ private String mKeystoreAlias;
+
+ private X500Principal mSubjectDN;
+
+ private BigInteger mSerialNumber;
+
+ private Date mStartDate;
+
+ private Date mEndDate;
+
+ public Builder(Context context) {
+ if (context == null) {
+ throw new NullPointerException("context == null");
+ }
+ mContext = context;
+ }
+
+ /**
+ * Sets the alias to be used to retrieve the key later from a
+ * {@link java.security.KeyStore} instance using the
+ * {@code AndroidKeyStore} provider.
+ */
+ public Builder setAlias(String alias) {
+ if (alias == null) {
+ throw new NullPointerException("alias == null");
+ }
+ mKeystoreAlias = alias;
+ return this;
+ }
+
+ /**
+ * Sets the subject used for the self-signed certificate of the
+ * generated key pair.
+ */
+ public Builder setSubject(X500Principal subject) {
+ if (subject == null) {
+ throw new NullPointerException("subject == null");
+ }
+ mSubjectDN = subject;
+ return this;
+ }
+
+ /**
+ * Sets the serial number used for the self-signed certificate of the
+ * generated key pair.
+ */
+ public Builder setSerialNumber(BigInteger serialNumber) {
+ if (serialNumber == null) {
+ throw new NullPointerException("serialNumber == null");
+ }
+ mSerialNumber = serialNumber;
+ return this;
+ }
+
+ /**
+ * Sets the start of the validity period for the self-signed certificate
+ * of the generated key pair.
+ */
+ public Builder setStartDate(Date startDate) {
+ if (startDate == null) {
+ throw new NullPointerException("startDate == null");
+ }
+ mStartDate = startDate;
+ return this;
+ }
+
+ /**
+ * Sets the end of the validity period for the self-signed certificate
+ * of the generated key pair.
+ */
+ public Builder setEndDate(Date endDate) {
+ if (endDate == null) {
+ throw new NullPointerException("endDate == null");
+ }
+ mEndDate = endDate;
+ return this;
+ }
+
+ /**
+ * Builds the instance of the {@code AndroidKeyPairGeneratorSpec}.
+ *
+ * @throws IllegalArgumentException if a required field is missing
+ * @return built instance of {@code AndroidKeyPairGeneratorSpec}
+ */
+ public AndroidKeyPairGeneratorSpec build() {
+ return new AndroidKeyPairGeneratorSpec(mContext, mKeystoreAlias, mSubjectDN,
+ mSerialNumber, mStartDate, mEndDate);
+ }
+ }
}
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index 65d7b8ff0bec..8a9826bd6176 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -453,17 +453,19 @@ public class AndroidKeyStore extends KeyStoreSpi {
* convention.
*/
final String[] certAliases = mKeyStore.saw(Credentials.USER_CERTIFICATE);
- for (String alias : certAliases) {
- final byte[] certBytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
- if (certBytes == null) {
- continue;
- }
+ if (certAliases != null) {
+ for (String alias : certAliases) {
+ final byte[] certBytes = mKeyStore.get(Credentials.USER_CERTIFICATE + alias);
+ if (certBytes == null) {
+ continue;
+ }
- final Certificate c = toCertificate(certBytes);
- nonCaEntries.add(alias);
+ final Certificate c = toCertificate(certBytes);
+ nonCaEntries.add(alias);
- if (cert.equals(c)) {
- return alias;
+ if (cert.equals(c)) {
+ return alias;
+ }
}
}
@@ -472,19 +474,22 @@ public class AndroidKeyStore extends KeyStoreSpi {
* PrivateKeyEntry we looked at above.
*/
final String[] caAliases = mKeyStore.saw(Credentials.CA_CERTIFICATE);
- for (String alias : caAliases) {
- if (nonCaEntries.contains(alias)) {
- continue;
- }
+ if (certAliases != null) {
+ for (String alias : caAliases) {
+ if (nonCaEntries.contains(alias)) {
+ continue;
+ }
- final byte[] certBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
- if (certBytes == null) {
- continue;
- }
+ final byte[] certBytes = mKeyStore.get(Credentials.CA_CERTIFICATE + alias);
+ if (certBytes == null) {
+ continue;
+ }
- final Certificate c = toCertificate(mKeyStore.get(Credentials.CA_CERTIFICATE + alias));
- if (cert.equals(c)) {
- return alias;
+ final Certificate c =
+ toCertificate(mKeyStore.get(Credentials.CA_CERTIFICATE + alias));
+ if (cert.equals(c)) {
+ return alias;
+ }
}
}
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index d8109ce2df99..166849dd8cc1 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -49,6 +49,8 @@ public class Credentials {
public static final String INSTALL_ACTION = "android.credentials.INSTALL";
+ public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER";
+
public static final String UNLOCK_ACTION = "com.android.credentials.UNLOCK";
/** Key prefix for CA certificates. */
@@ -83,6 +85,12 @@ public class Credentials {
public static final String EXTENSION_PFX = ".pfx";
/**
+ * Intent extra: install the certificate bundle as this UID instead of
+ * system.
+ */
+ public static final String EXTRA_INSTALL_AS_UID = "install_as_uid";
+
+ /**
* Intent extra: name for the user's private key.
*/
public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name";
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 4b6931744821..20374724dd24 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -87,42 +87,58 @@ public class KeyStore {
}
}
- public boolean put(String key, byte[] value) {
+ public boolean put(String key, byte[] value, int uid) {
try {
- return mBinder.insert(key, value, -1) == NO_ERROR;
+ return mBinder.insert(key, value, uid) == NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
}
}
- public boolean delete(String key) {
+ public boolean put(String key, byte[] value) {
+ return put(key, value, -1);
+ }
+
+ public boolean delete(String key, int uid) {
try {
- return mBinder.del(key, -1) == NO_ERROR;
+ return mBinder.del(key, uid) == NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
}
}
- public boolean contains(String key) {
+ public boolean delete(String key) {
+ return delete(key, -1);
+ }
+
+ public boolean contains(String key, int uid) {
try {
- return mBinder.exist(key, -1) == NO_ERROR;
+ return mBinder.exist(key, uid) == NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
}
}
- public String[] saw(String prefix) {
+ public boolean contains(String key) {
+ return contains(key, -1);
+ }
+
+ public String[] saw(String prefix, int uid) {
try {
- return mBinder.saw(prefix, -1);
+ return mBinder.saw(prefix, uid);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
}
}
+ public String[] saw(String prefix) {
+ return saw(prefix, -1);
+ }
+
public boolean reset() {
try {
return mBinder.reset() == NO_ERROR;
@@ -169,24 +185,32 @@ public class KeyStore {
}
}
- public boolean generate(String key) {
+ public boolean generate(String key, int uid) {
try {
- return mBinder.generate(key, -1) == NO_ERROR;
+ return mBinder.generate(key, uid) == NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
}
}
- public boolean importKey(String keyName, byte[] key) {
+ public boolean generate(String key) {
+ return generate(key, -1);
+ }
+
+ public boolean importKey(String keyName, byte[] key, int uid) {
try {
- return mBinder.import_key(keyName, key, -1) == NO_ERROR;
+ return mBinder.import_key(keyName, key, uid) == NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
}
}
+ public boolean importKey(String keyName, byte[] key) {
+ return importKey(keyName, key, -1);
+ }
+
public byte[] getPubkey(String key) {
try {
return mBinder.get_pubkey(key);
@@ -196,15 +220,19 @@ public class KeyStore {
}
}
- public boolean delKey(String key) {
+ public boolean delKey(String key, int uid) {
try {
- return mBinder.del_key(key, -1) == NO_ERROR;
+ return mBinder.del_key(key, uid) == NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
}
}
+ public boolean delKey(String key) {
+ return delKey(key, -1);
+ }
+
public byte[] sign(String key, byte[] data) {
try {
return mBinder.sign(key, data);
@@ -259,6 +287,24 @@ public class KeyStore {
}
}
+ public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
+ try {
+ return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return false;
+ }
+ }
+
+ public boolean isHardwareBacked() {
+ try {
+ return mBinder.is_hardware_backed() == NO_ERROR;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return false;
+ }
+ }
+
public int getLastError() {
return mError;
}
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
index e6a3750e1d0a..3d275cd72d0b 100644
--- a/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
@@ -53,6 +53,26 @@ public class AndroidKeyPairGeneratorSpecTest extends AndroidTestCase {
assertEquals("endDate should be the one specified", NOW_PLUS_10_YEARS, spec.getEndDate());
}
+ public void testBuilder_Success() throws Exception {
+ AndroidKeyPairGeneratorSpec spec = new AndroidKeyPairGeneratorSpec.Builder(getContext())
+ .setAlias(TEST_ALIAS_1)
+ .setSubject(TEST_DN_1)
+ .setSerialNumber(SERIAL_1)
+ .setStartDate(NOW)
+ .setEndDate(NOW_PLUS_10_YEARS)
+ .build();
+
+ assertEquals("Context should be the one specified", getContext(), spec.getContext());
+
+ assertEquals("Alias should be the one specified", TEST_ALIAS_1, spec.getKeystoreAlias());
+
+ assertEquals("subjectDN should be the one specified", TEST_DN_1, spec.getSubjectDN());
+
+ assertEquals("startDate should be the one specified", NOW, spec.getStartDate());
+
+ assertEquals("endDate should be the one specified", NOW_PLUS_10_YEARS, spec.getEndDate());
+ }
+
public void testConstructor_NullContext_Failure() throws Exception {
try {
new AndroidKeyPairGeneratorSpec(null, TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
index cd031b479f92..69007c43f978 100644
--- a/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
@@ -67,7 +67,9 @@ public class AndroidKeyPairGeneratorTest extends AndroidTestCase {
assertTrue(mAndroidKeyStore.password("1111"));
assertTrue(mAndroidKeyStore.isUnlocked());
- assertEquals(0, mAndroidKeyStore.saw("").length);
+ String[] aliases = mAndroidKeyStore.saw("");
+ assertNotNull(aliases);
+ assertEquals(0, aliases.length);
mGenerator = java.security.KeyPairGenerator.getInstance(AndroidKeyPairGenerator.NAME);
}
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 07a2d7b9a828..1de1eaf5bd50 100644
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -17,6 +17,7 @@
package android.security;
import android.app.Activity;
+import android.os.Process;
import android.security.KeyStore;
import android.test.ActivityUnitTestCase;
import android.test.AssertionFailedError;
@@ -128,7 +129,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
super.tearDown();
}
- public void teststate() throws Exception {
+ public void testState() throws Exception {
assertEquals(KeyStore.State.UNINITIALIZED, mKeyStore.state());
}
@@ -154,6 +155,24 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
}
+ public void testPut_grantedUid_Wifi() throws Exception {
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ mKeyStore.password(TEST_PASSWD);
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ }
+
+ public void testPut_ungrantedUid_Bluetooth() throws Exception {
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ mKeyStore.password(TEST_PASSWD);
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ }
+
public void testI18n() throws Exception {
assertFalse(mKeyStore.put(TEST_I18N_KEY, TEST_I18N_VALUE));
assertFalse(mKeyStore.contains(TEST_I18N_KEY));
@@ -167,22 +186,64 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
mKeyStore.password(TEST_PASSWD);
assertFalse(mKeyStore.delete(TEST_KEYNAME));
- mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
assertTrue(Arrays.equals(TEST_KEYVALUE, mKeyStore.get(TEST_KEYNAME)));
assertTrue(mKeyStore.delete(TEST_KEYNAME));
assertNull(mKeyStore.get(TEST_KEYNAME));
}
+ public void testDelete_grantedUid_Wifi() throws Exception {
+ assertFalse(mKeyStore.delete(TEST_KEYNAME, Process.WIFI_UID));
+ mKeyStore.password(TEST_PASSWD);
+ assertFalse(mKeyStore.delete(TEST_KEYNAME, Process.WIFI_UID));
+
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ assertTrue(mKeyStore.delete(TEST_KEYNAME, Process.WIFI_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ }
+
+ public void testDelete_ungrantedUid_Bluetooth() throws Exception {
+ assertFalse(mKeyStore.delete(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ mKeyStore.password(TEST_PASSWD);
+ assertFalse(mKeyStore.delete(TEST_KEYNAME, Process.BLUETOOTH_UID));
+
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.delete(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ }
+
public void testContains() throws Exception {
assertFalse(mKeyStore.contains(TEST_KEYNAME));
- mKeyStore.password(TEST_PASSWD);
+ assertTrue(mKeyStore.password(TEST_PASSWD));
assertFalse(mKeyStore.contains(TEST_KEYNAME));
- mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE);
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE));
assertTrue(mKeyStore.contains(TEST_KEYNAME));
}
+ public void testContains_grantedUid_Wifi() throws Exception {
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+
+ assertTrue(mKeyStore.password(TEST_PASSWD));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+
+ assertTrue(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ }
+
+ public void testContains_grantedUid_Bluetooth() throws Exception {
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+
+ assertTrue(mKeyStore.password(TEST_PASSWD));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+
+ assertFalse(mKeyStore.put(TEST_KEYNAME, TEST_KEYVALUE, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ }
+
public void testSaw() throws Exception {
String[] emptyResult = mKeyStore.saw(TEST_KEYNAME);
assertNotNull(emptyResult);
@@ -198,6 +259,48 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
new HashSet(Arrays.asList(results)));
}
+ public void testSaw_ungrantedUid_Bluetooth() throws Exception {
+ String[] results1 = mKeyStore.saw(TEST_KEYNAME, Process.BLUETOOTH_UID);
+ assertNull(results1);
+
+ mKeyStore.password(TEST_PASSWD);
+ mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE);
+ mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE);
+
+ String[] results2 = mKeyStore.saw(TEST_KEYNAME, Process.BLUETOOTH_UID);
+ assertNull(results2);
+ }
+
+ public void testSaw_grantedUid_Wifi() throws Exception {
+ String[] results1 = mKeyStore.saw(TEST_KEYNAME, Process.WIFI_UID);
+ assertNotNull(results1);
+ assertEquals(0, results1.length);
+
+ mKeyStore.password(TEST_PASSWD);
+ mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, Process.WIFI_UID);
+ mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, Process.WIFI_UID);
+
+ String[] results2 = mKeyStore.saw(TEST_KEYNAME, Process.WIFI_UID);
+ assertEquals(new HashSet(Arrays.asList(TEST_KEYNAME1.substring(TEST_KEYNAME.length()),
+ TEST_KEYNAME2.substring(TEST_KEYNAME.length()))),
+ new HashSet(Arrays.asList(results2)));
+ }
+
+ public void testSaw_grantedUid_Vpn() throws Exception {
+ String[] results1 = mKeyStore.saw(TEST_KEYNAME, Process.VPN_UID);
+ assertNotNull(results1);
+ assertEquals(0, results1.length);
+
+ mKeyStore.password(TEST_PASSWD);
+ mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, Process.VPN_UID);
+ mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, Process.VPN_UID);
+
+ String[] results2 = mKeyStore.saw(TEST_KEYNAME, Process.VPN_UID);
+ assertEquals(new HashSet(Arrays.asList(TEST_KEYNAME1.substring(TEST_KEYNAME.length()),
+ TEST_KEYNAME2.substring(TEST_KEYNAME.length()))),
+ new HashSet(Arrays.asList(results2)));
+ }
+
public void testLock() throws Exception {
assertFalse(mKeyStore.lock());
@@ -239,17 +342,57 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
}
public void testGenerate_Success() throws Exception {
- mKeyStore.password(TEST_PASSWD);
+ assertTrue(mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to generate key when unlocked",
mKeyStore.generate(TEST_KEYNAME));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ }
+
+ public void testGenerate_grantedUid_Wifi_Success() throws Exception {
+ assertTrue(mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to generate key when unlocked",
+ mKeyStore.generate(TEST_KEYNAME, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME));
+ }
+
+ public void testGenerate_ungrantedUid_Bluetooth_Failure() throws Exception {
+ assertTrue(mKeyStore.password(TEST_PASSWD));
+
+ assertFalse(mKeyStore.generate(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME));
}
public void testImport_Success() throws Exception {
- mKeyStore.password(TEST_PASSWD);
+ assertTrue(mKeyStore.password(TEST_PASSWD));
assertTrue("Should be able to import key when unlocked",
mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ }
+
+ public void testImport_grantedUid_Wifi_Success() throws Exception {
+ assertTrue(mKeyStore.password(TEST_PASSWD));
+
+ assertTrue("Should be able to import key when unlocked",
+ mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME));
+ }
+
+ public void testImport_ungrantedUid_Bluetooth_Failure() throws Exception {
+ assertTrue(mKeyStore.password(TEST_PASSWD));
+
+ assertFalse(mKeyStore.importKey(TEST_KEYNAME, PRIVKEY_BYTES, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME));
}
public void testImport_Failure_BadEncoding() throws Exception {
@@ -257,12 +400,15 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
assertFalse("Invalid DER-encoded key should not be imported",
mKeyStore.importKey(TEST_KEYNAME, TEST_DATA));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
}
public void testSign_Success() throws Exception {
mKeyStore.password(TEST_PASSWD);
assertTrue(mKeyStore.generate(TEST_KEYNAME));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA);
assertNotNull("Signature should not be null", signature);
@@ -272,6 +418,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
mKeyStore.password(TEST_PASSWD);
assertTrue(mKeyStore.generate(TEST_KEYNAME));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA);
assertNotNull("Signature should not be null", signature);
@@ -406,6 +553,62 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> {
mKeyStore.ungrant(TEST_KEYNAME, 0));
}
+ public void testDuplicate_grantedUid_Wifi_Success() throws Exception {
+ assertTrue(mKeyStore.password(TEST_PASSWD));
+
+ assertFalse(mKeyStore.contains(TEST_KEYNAME));
+
+ assertTrue(mKeyStore.generate(TEST_KEYNAME));
+
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+
+ // source doesn't exist
+ assertFalse(mKeyStore.duplicate(TEST_KEYNAME1, -1, TEST_KEYNAME1, Process.WIFI_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME1, Process.WIFI_UID));
+
+ // Copy from current UID to granted UID
+ assertTrue(mKeyStore.duplicate(TEST_KEYNAME, -1, TEST_KEYNAME1, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME1));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME1, Process.WIFI_UID));
+ assertFalse(mKeyStore.duplicate(TEST_KEYNAME, -1, TEST_KEYNAME1, Process.WIFI_UID));
+
+ // Copy from granted UID to same granted UID
+ assertTrue(mKeyStore.duplicate(TEST_KEYNAME1, Process.WIFI_UID, TEST_KEYNAME2,
+ Process.WIFI_UID));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME1, Process.WIFI_UID));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME2, Process.WIFI_UID));
+ assertFalse(mKeyStore.duplicate(TEST_KEYNAME1, Process.WIFI_UID, TEST_KEYNAME2,
+ Process.WIFI_UID));
+
+ assertTrue(mKeyStore.duplicate(TEST_KEYNAME, -1, TEST_KEYNAME2, -1));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME1));
+ assertTrue(mKeyStore.contains(TEST_KEYNAME2));
+ assertFalse(mKeyStore.duplicate(TEST_KEYNAME, -1, TEST_KEYNAME2, -1));
+ }
+
+ public void testDuplicate_ungrantedUid_Bluetooth_Failure() throws Exception {
+ assertTrue(mKeyStore.password(TEST_PASSWD));
+
+ assertFalse(mKeyStore.contains(TEST_KEYNAME));
+
+ assertTrue(mKeyStore.generate(TEST_KEYNAME));
+
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+
+ assertFalse(mKeyStore.duplicate(TEST_KEYNAME, -1, TEST_KEYNAME2, Process.BLUETOOTH_UID));
+ assertFalse(mKeyStore.duplicate(TEST_KEYNAME, Process.BLUETOOTH_UID, TEST_KEYNAME2,
+ Process.BLUETOOTH_UID));
+
+ assertTrue(mKeyStore.contains(TEST_KEYNAME));
+ assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID));
+ }
+
/**
* The amount of time to allow before and after expected time for variance
* in timing tests.
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
index e80b325e6e32..e80b325e6e32 100755..100644
--- a/libs/hwui/Dither.cpp
+++ b/libs/hwui/Dither.cpp
diff --git a/libs/hwui/Dither.h b/libs/hwui/Dither.h
index 34cf9bf6a4b7..34cf9bf6a4b7 100755..100644
--- a/libs/hwui/Dither.h
+++ b/libs/hwui/Dither.h
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 8eb933247472..756638c0f6f8 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -48,7 +48,7 @@ public class ThumbnailUtils {
/* Maximum pixels size for created bitmap. */
private static final int MAX_NUM_PIXELS_THUMBNAIL = 512 * 384;
- private static final int MAX_NUM_PIXELS_MICRO_THUMBNAIL = 128 * 128;
+ private static final int MAX_NUM_PIXELS_MICRO_THUMBNAIL = 160 * 120;
private static final int UNCONSTRAINED = -1;
/* Options used internally. */
diff --git a/media/jni/mediaeditor/VideoBrowserMain.c b/media/jni/mediaeditor/VideoBrowserMain.c
index c6c6000ce6bc..c6c6000ce6bc 100755..100644
--- a/media/jni/mediaeditor/VideoBrowserMain.c
+++ b/media/jni/mediaeditor/VideoBrowserMain.c
diff --git a/media/tests/EffectsTest/Android.mk b/media/tests/EffectsTest/Android.mk
index 25b4fe495914..25b4fe495914 100755..100644
--- a/media/tests/EffectsTest/Android.mk
+++ b/media/tests/EffectsTest/Android.mk
diff --git a/media/tests/EffectsTest/AndroidManifest.xml b/media/tests/EffectsTest/AndroidManifest.xml
index 9b59891fb279..9b59891fb279 100755..100644
--- a/media/tests/EffectsTest/AndroidManifest.xml
+++ b/media/tests/EffectsTest/AndroidManifest.xml
diff --git a/media/tests/EffectsTest/res/drawable/icon.png b/media/tests/EffectsTest/res/drawable/icon.png
index 64e3601c234d..64e3601c234d 100755..100644
--- a/media/tests/EffectsTest/res/drawable/icon.png
+++ b/media/tests/EffectsTest/res/drawable/icon.png
Binary files differ
diff --git a/media/tests/EffectsTest/res/drawable/stop.png b/media/tests/EffectsTest/res/drawable/stop.png
index 83f012ca2b56..83f012ca2b56 100755..100644
--- a/media/tests/EffectsTest/res/drawable/stop.png
+++ b/media/tests/EffectsTest/res/drawable/stop.png
Binary files differ
diff --git a/media/tests/EffectsTest/res/layout/bassboosttest.xml b/media/tests/EffectsTest/res/layout/bassboosttest.xml
index ac912c84d107..ac912c84d107 100755..100644
--- a/media/tests/EffectsTest/res/layout/bassboosttest.xml
+++ b/media/tests/EffectsTest/res/layout/bassboosttest.xml
diff --git a/media/tests/EffectsTest/res/layout/effectstest.xml b/media/tests/EffectsTest/res/layout/effectstest.xml
index 9af4eb6ef22a..9af4eb6ef22a 100755..100644
--- a/media/tests/EffectsTest/res/layout/effectstest.xml
+++ b/media/tests/EffectsTest/res/layout/effectstest.xml
diff --git a/media/tests/EffectsTest/res/layout/envreverbtest.xml b/media/tests/EffectsTest/res/layout/envreverbtest.xml
index 01c324080294..01c324080294 100755..100644
--- a/media/tests/EffectsTest/res/layout/envreverbtest.xml
+++ b/media/tests/EffectsTest/res/layout/envreverbtest.xml
diff --git a/media/tests/EffectsTest/res/layout/equalizertest.xml b/media/tests/EffectsTest/res/layout/equalizertest.xml
index 5ef035da676d..5ef035da676d 100755..100644
--- a/media/tests/EffectsTest/res/layout/equalizertest.xml
+++ b/media/tests/EffectsTest/res/layout/equalizertest.xml
diff --git a/media/tests/EffectsTest/res/layout/presetreverbtest.xml b/media/tests/EffectsTest/res/layout/presetreverbtest.xml
index cd7fbd3a6d50..cd7fbd3a6d50 100755..100644
--- a/media/tests/EffectsTest/res/layout/presetreverbtest.xml
+++ b/media/tests/EffectsTest/res/layout/presetreverbtest.xml
diff --git a/media/tests/EffectsTest/res/layout/virtualizertest.xml b/media/tests/EffectsTest/res/layout/virtualizertest.xml
index 1fafeab3abdb..1fafeab3abdb 100755..100644
--- a/media/tests/EffectsTest/res/layout/virtualizertest.xml
+++ b/media/tests/EffectsTest/res/layout/virtualizertest.xml
diff --git a/media/tests/EffectsTest/res/layout/visualizertest.xml b/media/tests/EffectsTest/res/layout/visualizertest.xml
index 50ac7bbd8cd0..50ac7bbd8cd0 100755..100644
--- a/media/tests/EffectsTest/res/layout/visualizertest.xml
+++ b/media/tests/EffectsTest/res/layout/visualizertest.xml
diff --git a/media/tests/EffectsTest/res/values/strings.xml b/media/tests/EffectsTest/res/values/strings.xml
index 2a8518417565..2a8518417565 100755..100644
--- a/media/tests/EffectsTest/res/values/strings.xml
+++ b/media/tests/EffectsTest/res/values/strings.xml
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
index 1a10d6422184..1a10d6422184 100755..100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java b/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java
index 95077e79b272..95077e79b272 100755..100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EffectParameter.java
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java
index 70202463a79e..70202463a79e 100755..100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EffectsTest.java
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
index 594e8446faa7..594e8446faa7 100755..100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
index f30a26f39c64..f30a26f39c64 100755..100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java b/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java
index 91d79483ea93..91d79483ea93 100755..100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/PresetReverbTest.java
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
index bb32e6fa7603..bb32e6fa7603 100755..100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
index 60583e0adf72..60583e0adf72 100755..100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 9da883a7f4c7..8d0fe75543c6 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -378,6 +378,7 @@ public class ImageWallpaper extends WallpaperService {
if (DEBUG) {
Log.d(TAG, "Redrawing wallpaper");
}
+
if (mIsHwAccelerated) {
if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
@@ -640,13 +641,26 @@ public class ImageWallpaper extends WallpaperService {
}
mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
+
+ int[] maxSize = new int[1];
+ Rect frame = surfaceHolder.getSurfaceFrame();
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0);
+ if(frame.width() > maxSize[0] || frame.height() > maxSize[0]) {
+ mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+ mEgl.eglTerminate(mEglDisplay);
+ Log.e(GL_LOG_TAG, "requested texture size " +
+ frame.width() + "x" + frame.height() + " exceeds the support maximum of " +
+ maxSize[0] + "x" + maxSize[0]);
+ return false;
+ }
mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null);
if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
int error = mEgl.eglGetError();
- if (error == EGL_BAD_NATIVE_WINDOW) {
- Log.e(GL_LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
+ if (error == EGL_BAD_NATIVE_WINDOW || error == EGL_BAD_ALLOC) {
+ Log.e(GL_LOG_TAG, "createWindowSurface returned " +
+ GLUtils.getEGLErrorString(error) + ".");
return false;
}
throw new RuntimeException("createWindowSurface failed " +
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
index 0f894a154f39..0f894a154f39 100755..100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 30af333f7669..7d7e7a328965 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -415,6 +415,7 @@ public class PhoneStatusBar extends BaseStatusBar {
mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);
mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
+ mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
mTickerView = mStatusBarView.findViewById(R.id.ticker);
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 3dc77d49feab..3dc77d49feab 100755..100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index fb515ac1e722..0f4262a1f7a6 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1523,6 +1523,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return null;
}
+ WindowManager wm = null;
+ View view = null;
+
try {
Context context = mContext;
if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
@@ -1582,8 +1585,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
params.setTitle("Starting " + packageName);
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- View view = win.getDecorView();
+ wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ view = win.getDecorView();
if (win.isFloating()) {
// Whoops, there is no way to display an animation/preview
@@ -1613,6 +1616,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// failure loading resources because we are loading from an app
// on external storage that has been unmounted.
Log.w(TAG, appToken + " failed creating starting window", e);
+ } finally {
+ if (view != null && view.getParent() == null) {
+ Log.w(TAG, "view not successfully added to wm, removing view");
+ wm.removeViewImmediate(view);
+ }
}
return null;
diff --git a/preloaded-classes b/preloaded-classes
index 10c5c9e704c9..126dd15fe5aa 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -199,16 +199,14 @@ android.app.backup.BackupHelperDispatcher$Header
android.app.backup.FileBackupHelperBase
android.app.backup.FullBackup
android.appwidget.AppWidgetManager
-android.bluetooth.BluetoothAudioGateway
android.bluetooth.BluetoothSocket
-android.bluetooth.HeadsetBase
android.bluetooth.IBluetooth
android.bluetooth.IBluetooth$Stub
android.bluetooth.IBluetoothA2dp
android.bluetooth.IBluetoothA2dp$Stub
android.content.AbstractThreadedSyncAdapter
android.content.AbstractThreadedSyncAdapter$ISyncAdapterImpl
-undroid.content.AbstractThreadedSyncAdapter$SyncThread
+android.content.AbstractThreadedSyncAdapter$SyncThread
android.content.BroadcastReceiver
android.content.BroadcastReceiver$PendingResult
android.content.ComponentCallbacks
@@ -737,9 +735,6 @@ android.provider.Settings$NameValueTable
android.provider.Settings$Secure
android.provider.Settings$System
android.renderscript.RenderScript
-android.server.BluetoothA2dpService
-android.server.BluetoothEventLoop
-android.server.BluetoothService
android.telephony.PhoneNumberUtils
android.telephony.TelephonyManager
android.text.AndroidBidi
@@ -844,7 +839,6 @@ android.util.EventLog$Event
android.util.FinitePool
android.util.FloatMath
android.util.FloatProperty
-android.util.LocaleUtil
android.util.Log
android.util.Log$1
android.util.Log$TerribleFailureHandler
@@ -1022,7 +1016,6 @@ android.view.ViewRootImpl$ConsumeBatchedInputRunnable
android.view.ViewRootImpl$InputMethodCallback
android.view.ViewRootImpl$InvalidateOnAnimationRunnable
android.view.ViewRootImpl$QueuedInputEvent
-android.view.ViewRootImpl$ResizedInfo
android.view.ViewRootImpl$RunQueue
android.view.ViewRootImpl$RunQueue$HandlerAction
android.view.ViewRootImpl$TrackballAxis
@@ -1042,7 +1035,6 @@ android.view.ViewTreeObserver$OnScrollChangedListener
android.view.ViewTreeObserver$OnTouchModeChangeListener
android.view.Window
android.view.Window$Callback
-android.view.Window$LocalWindowManager
android.view.WindowLeaked
android.view.WindowManager
android.view.WindowManager$LayoutParams
@@ -1050,7 +1042,6 @@ android.view.WindowManager$LayoutParams$1
android.view.WindowManagerGlobal
android.view.WindowManagerGlobal$1
android.view.WindowManagerImpl
-android.view.WindowManagerImpl$CompatModeWrapper
android.view.accessibility.AccessibilityEvent
android.view.accessibility.AccessibilityEventSource
android.view.accessibility.AccessibilityManager
@@ -1843,7 +1834,6 @@ java.text.CharacterIterator
java.text.DateFormat
java.text.DateFormatSymbols
java.text.DecimalFormat
-java.text.DecimalFormat$1
java.text.DecimalFormatSymbols
java.text.FieldPosition
java.text.Format
@@ -1995,7 +1985,6 @@ java.util.concurrent.Executors$FinalizableDelegatedExecutorService
java.util.concurrent.Future
java.util.concurrent.FutureTask
java.util.concurrent.FutureTask$WaitNode
-java.util.concurrent.FutureTask$Sync
java.util.concurrent.LinkedBlockingQueue
java.util.concurrent.LinkedBlockingQueue$Node
java.util.concurrent.RejectedExecutionHandler
@@ -2015,7 +2004,6 @@ java.util.concurrent.TimeUnit$7
java.util.concurrent.atomic.AtomicBoolean
java.util.concurrent.atomic.AtomicInteger
java.util.concurrent.atomic.AtomicReference
-java.util.concurrent.atomic.UnsafeAccess
java.util.concurrent.locks.AbstractOwnableSynchronizer
java.util.concurrent.locks.AbstractQueuedSynchronizer
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject
@@ -2034,7 +2022,6 @@ java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock
java.util.concurrent.locks.ReentrantReadWriteLock$Sync
java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter
java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock
-java.util.concurrent.locks.UnsafeAccess
java.util.jar.Attributes
java.util.jar.Attributes$Name
java.util.jar.InitManifest
@@ -2111,7 +2098,6 @@ javax.net.ssl.X509ExtendedKeyManager
javax.net.ssl.X509KeyManager
javax.net.ssl.X509TrustManager
javax.security.auth.x500.X500Principal
-libcore.icu.ErrorCode
libcore.icu.ICU
libcore.icu.LocaleData
libcore.icu.NativeBreakIterator
@@ -2122,7 +2108,7 @@ libcore.icu.NativeDecimalFormat$FieldPositionIterator
libcore.icu.NativeIDN
libcore.icu.NativeNormalizer
libcore.icu.NativePluralRules
-libcore.icu.TimeZones
+libcore.icu.TimeZoneNames
libcore.internal.StringPool
libcore.io.AsynchronousCloseMonitor
libcore.io.Base64
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 7ac314b8a7a9..b0561df5aaf7 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -63,6 +63,7 @@ import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SELinux;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -743,6 +744,9 @@ class BackupManagerService extends IBackupManager.Stub {
// correct directory.
mBaseStateDir = new File(Environment.getSecureDataDirectory(), "backup");
mBaseStateDir.mkdirs();
+ if (!SELinux.restorecon(mBaseStateDir)) {
+ Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir);
+ }
mDataDir = Environment.getDownloadCacheDirectory();
mPasswordHashFile = new File(mBaseStateDir, "pwhash");
@@ -2133,6 +2137,10 @@ class BackupManagerService extends IBackupManager.Stub {
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE);
+ if (!SELinux.restorecon(mBackupDataName)) {
+ Slog.e(TAG, "SELinux restorecon failed on " + mBackupDataName);
+ }
+
mNewState = ParcelFileDescriptor.open(mNewStateName,
ParcelFileDescriptor.MODE_READ_WRITE |
ParcelFileDescriptor.MODE_CREATE |
@@ -3795,7 +3803,7 @@ class BackupManagerService extends IBackupManager.Stub {
b.append(String.format(" %9d ", info.size));
Date stamp = new Date(info.mtime);
- b.append(new SimpleDateFormat("MMM dd kk:mm:ss ").format(stamp));
+ b.append(new SimpleDateFormat("MMM dd HH:mm:ss ").format(stamp));
b.append(info.packageName);
b.append(" :: ");
@@ -4572,6 +4580,10 @@ class BackupManagerService extends IBackupManager.Stub {
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE);
+ if (!SELinux.restorecon(mBackupDataName)) {
+ Slog.e(TAG, "SElinux restorecon failed for " + mBackupDataName);
+ }
+
if (mTransport.getRestoreData(mBackupData) != BackupConstants.TRANSPORT_OK) {
// Transport-level failure, so we wind everything up and
// terminate the restore operation.
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
index 5a2088ce01c7..5a2088ce01c7 100755..100644
--- a/services/java/com/android/server/BluetoothManagerService.java
+++ b/services/java/com/android/server/BluetoothManagerService.java
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 2e0c977d2ec5..ce83a4578669 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -1577,7 +1577,7 @@ class MountService extends IMountService.Stub
boolean mounted = false;
try {
mounted = Environment.MEDIA_MOUNTED.equals(getVolumeState(primary.getPath()));
- } catch (IllegalStateException e) {
+ } catch (IllegalArgumentException e) {
}
if (!mounted) {
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index b2a8ad834dc4..1663106964dc 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -29,6 +29,7 @@ import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Debug;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.ServiceManager;
@@ -114,6 +115,10 @@ public class Watchdog extends Thread {
* Used for scheduling monitor callbacks and checking memory usage.
*/
final class HeartbeatHandler extends Handler {
+ HeartbeatHandler(Looper looper) {
+ super(looper);
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -183,7 +188,9 @@ public class Watchdog extends Thread {
private Watchdog() {
super("watchdog");
- mHandler = new HeartbeatHandler();
+ // Explicitly bind the HeartbeatHandler to run on the ServerThread, so
+ // that it can't get accidentally bound to another thread.
+ mHandler = new HeartbeatHandler(Looper.getMainLooper());
}
public void init(Context context, BatteryService battery,
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6e81e9d0cb93..c6efe15b9ced 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2171,7 +2171,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, null, null);
+ app.info.targetSdkVersion, app.info.seinfo, null);
BatteryStatsImpl bs = app.batteryStats.getBatteryStats();
synchronized (bs) {
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 71a6a0188230..6a071ef03f9e 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -188,7 +188,7 @@ public final class Installer {
}
}
- public int install(String name, int uid, int gid) {
+ public int install(String name, int uid, int gid, String seinfo) {
StringBuilder builder = new StringBuilder("install");
builder.append(' ');
builder.append(name);
@@ -196,6 +196,8 @@ public final class Installer {
builder.append(uid);
builder.append(' ');
builder.append(gid);
+ builder.append(' ');
+ builder.append(seinfo != null ? seinfo : "!");
return execute(builder.toString());
}
@@ -263,7 +265,7 @@ public final class Installer {
return execute(builder.toString());
}
- public int createUserData(String name, int uid, int userId) {
+ public int createUserData(String name, int uid, int userId, String seinfo) {
StringBuilder builder = new StringBuilder("mkuserdata");
builder.append(' ');
builder.append(name);
@@ -271,6 +273,8 @@ public final class Installer {
builder.append(uid);
builder.append(' ');
builder.append(userId);
+ builder.append(' ');
+ builder.append(seinfo != null ? seinfo : "!");
return execute(builder.toString());
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 2238f17621f1..b8324eeb2b60 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -352,6 +352,9 @@ public class PackageManagerService extends IPackageManager.Stub {
final HashMap<String, FeatureInfo> mAvailableFeatures =
new HashMap<String, FeatureInfo>();
+ // If mac_permissions.xml was found for seinfo labeling.
+ boolean mFoundPolicyFile;
+
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
@@ -1020,6 +1023,8 @@ public class PackageManagerService extends IPackageManager.Stub {
readPermissions();
+ mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
+
mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false),
mSdkVersion, mOnlyCore);
long startTime = SystemClock.uptimeMillis();
@@ -3582,16 +3587,16 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private int createDataDirsLI(String packageName, int uid) {
+ private int createDataDirsLI(String packageName, int uid, String seinfo) {
int[] users = sUserManager.getUserIds();
- int res = mInstaller.install(packageName, uid, uid);
+ int res = mInstaller.install(packageName, uid, uid, seinfo);
if (res < 0) {
return res;
}
for (int user : users) {
if (user != 0) {
res = mInstaller.createUserData(packageName,
- UserHandle.getUid(user, uid), user);
+ UserHandle.getUid(user, uid), user, seinfo);
if (res < 0) {
return res;
}
@@ -3847,6 +3852,10 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
+ if (mFoundPolicyFile) {
+ SELinuxMMAC.assignSeinfoValue(pkg);
+ }
+
pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting;
@@ -3985,7 +3994,8 @@ public class PackageManagerService extends IPackageManager.Stub {
recovered = true;
// And now re-install the app.
- ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
+ ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.seinfo);
if (ret == -1) {
// Ack should not happen!
msg = prefix + pkg.packageName
@@ -4031,7 +4041,8 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.v(TAG, "Want this data dir: " + dataPath);
}
//invoke installer to do the actual installation
- int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
+ int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
+ pkg.applicationInfo.seinfo);
if (ret < 0) {
// Error from installer
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/java/com/android/server/pm/SELinuxMMAC.java
new file mode 100644
index 000000000000..4bbdb5e26668
--- /dev/null
+++ b/services/java/com/android/server/pm/SELinuxMMAC.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 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.server.pm;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.Signature;
+import android.os.Environment;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.XmlUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+import java.util.HashMap;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Centralized access to SELinux MMAC (middleware MAC) implementation.
+ * {@hide}
+ */
+public final class SELinuxMMAC {
+
+ private static final String TAG = "SELinuxMMAC";
+
+ private static final boolean DEBUG_POLICY = false;
+ private static final boolean DEBUG_POLICY_INSTALL = DEBUG_POLICY || false;
+
+ // Signature seinfo values read from policy.
+ private static final HashMap<Signature, String> sSigSeinfo =
+ new HashMap<Signature, String>();
+
+ // Package name seinfo values read from policy.
+ private static final HashMap<String, String> sPackageSeinfo =
+ new HashMap<String, String>();
+
+ // Locations of potential install policy files.
+ private static final File[] INSTALL_POLICY_FILE = {
+ new File(Environment.getDataDirectory(), "system/mac_permissions.xml"),
+ new File(Environment.getRootDirectory(), "etc/security/mac_permissions.xml"),
+ null};
+
+ private static void flushInstallPolicy() {
+ sSigSeinfo.clear();
+ sPackageSeinfo.clear();
+ }
+
+ /**
+ * Parses an MMAC install policy from a predefined list of locations.
+ * @param none
+ * @return boolean indicating whether an install policy was correctly parsed.
+ */
+ public static boolean readInstallPolicy() {
+
+ return readInstallPolicy(INSTALL_POLICY_FILE);
+ }
+
+ /**
+ * Parses an MMAC install policy given as an argument.
+ * @param File object representing the path of the policy.
+ * @return boolean indicating whether the install policy was correctly parsed.
+ */
+ public static boolean readInstallPolicy(File policyFile) {
+
+ return readInstallPolicy(new File[]{policyFile,null});
+ }
+
+ private static boolean readInstallPolicy(File[] policyFiles) {
+
+ FileReader policyFile = null;
+ int i = 0;
+ while (policyFile == null && policyFiles != null && policyFiles[i] != null) {
+ try {
+ policyFile = new FileReader(policyFiles[i]);
+ break;
+ } catch (FileNotFoundException e) {
+ Slog.d(TAG,"Couldn't find install policy " + policyFiles[i].getPath());
+ }
+ i++;
+ }
+
+ if (policyFile == null) {
+ Slog.d(TAG, "No policy file found. All seinfo values will be null.");
+ return false;
+ }
+
+ Slog.d(TAG, "Using install policy file " + policyFiles[i].getPath());
+
+ flushInstallPolicy();
+
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(policyFile);
+
+ XmlUtils.beginDocument(parser, "policy");
+ while (true) {
+ XmlUtils.nextElement(parser);
+ if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
+ break;
+ }
+
+ String tagName = parser.getName();
+ if ("signer".equals(tagName)) {
+ String cert = parser.getAttributeValue(null, "signature");
+ if (cert == null) {
+ Slog.w(TAG, "<signer> without signature at "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ Signature signature;
+ try {
+ signature = new Signature(cert);
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG, "<signer> with bad signature at "
+ + parser.getPositionDescription(), e);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String seinfo = readSeinfoTag(parser);
+ if (seinfo != null) {
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "<signer> tag: (" + cert + ") assigned seinfo="
+ + seinfo);
+
+ sSigSeinfo.put(signature, seinfo);
+ }
+ } else if ("default".equals(tagName)) {
+ String seinfo = readSeinfoTag(parser);
+ if (seinfo != null) {
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "<default> tag assigned seinfo=" + seinfo);
+
+ // The 'null' signature is the default seinfo value
+ sSigSeinfo.put(null, seinfo);
+ }
+ } else if ("package".equals(tagName)) {
+ String pkgName = parser.getAttributeValue(null, "name");
+ if (pkgName == null) {
+ Slog.w(TAG, "<package> without name at "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String seinfo = readSeinfoTag(parser);
+ if (seinfo != null) {
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "<package> tag: (" + pkgName +
+ ") assigned seinfo=" + seinfo);
+
+ sPackageSeinfo.put(pkgName, seinfo);
+ }
+ } else {
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ }
+ } catch (XmlPullParserException e) {
+ Slog.w(TAG, "Got execption parsing ", e);
+ } catch (IOException e) {
+ Slog.w(TAG, "Got execption parsing ", e);
+ }
+ try {
+ policyFile.close();
+ } catch (IOException e) {
+ //omit
+ }
+ return true;
+ }
+
+ private static String readSeinfoTag(XmlPullParser parser) throws
+ IOException, XmlPullParserException {
+
+ int type;
+ int outerDepth = parser.getDepth();
+ String seinfo = null;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG
+ || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if ("seinfo".equals(tagName)) {
+ String seinfoValue = parser.getAttributeValue(null, "value");
+ if (validateValue(seinfoValue)) {
+ seinfo = seinfoValue;
+ } else {
+ Slog.w(TAG, "<seinfo> without valid value at "
+ + parser.getPositionDescription());
+ }
+ }
+ XmlUtils.skipCurrentTag(parser);
+ }
+ return seinfo;
+ }
+
+ /**
+ * General validation routine for tag values.
+ * Returns a boolean indicating if the passed string
+ * contains only letters or underscores.
+ */
+ private static boolean validateValue(String name) {
+ if (name == null)
+ return false;
+
+ final int N = name.length();
+ if (N == 0)
+ return false;
+
+ for (int i = 0; i < N; i++) {
+ final char c = name.charAt(i);
+ if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c != '_')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Labels a package based on an seinfo tag from install policy.
+ * The label is attached to the ApplicationInfo instance of the package.
+ * @param PackageParser.Package object representing the package
+ * to labeled.
+ * @return String holding the value of the seinfo label that was assigned.
+ * Value may be null which indicates no seinfo label was assigned.
+ */
+ public static void assignSeinfoValue(PackageParser.Package pkg) {
+
+ /*
+ * Non system installed apps should be treated the same. This
+ * means that any post-loaded apk will be assigned the default
+ * tag, if one exists in the policy, else null, without respect
+ * to the signing key.
+ */
+ if (((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) ||
+ ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)) {
+
+ // We just want one of the signatures to match.
+ for (Signature s : pkg.mSignatures) {
+ if (s == null)
+ continue;
+
+ if (sSigSeinfo.containsKey(s)) {
+ String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(s);
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "package (" + pkg.packageName +
+ ") labeled with seinfo=" + seinfo);
+
+ return;
+ }
+ }
+
+ // Check for seinfo labeled by package.
+ if (sPackageSeinfo.containsKey(pkg.packageName)) {
+ String seinfo = pkg.applicationInfo.seinfo = sPackageSeinfo.get(pkg.packageName);
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "package (" + pkg.packageName +
+ ") labeled with seinfo=" + seinfo);
+ return;
+ }
+ }
+
+ // If we have a default seinfo value then great, otherwise
+ // we set a null object and that is what we started with.
+ String seinfo = pkg.applicationInfo.seinfo = sSigSeinfo.get(null);
+ if (DEBUG_POLICY_INSTALL)
+ Slog.i(TAG, "package (" + pkg.packageName +
+ ") labeled with seinfo=" + (seinfo == null ? "null" : seinfo));
+ }
+}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 06f11bc9a4da..b744bc335b46 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1359,6 +1359,7 @@ final class Settings {
// userId - application-specific user id
// debugFlag - 0 or 1 if the package is debuggable.
// dataPath - path to package's data path
+ // seinfo - seinfo label for the app (assigned at install time)
//
// NOTE: We prefer not to expose all ApplicationInfo flags for now.
//
@@ -1372,6 +1373,8 @@ final class Settings {
sb.append((int)ai.uid);
sb.append(isDebug ? " 1 " : " 0 ");
sb.append(dataPath);
+ sb.append(" ");
+ sb.append(ai.seinfo);
sb.append("\n");
str.write(sb.toString().getBytes());
}
@@ -2337,7 +2340,8 @@ final class Settings {
ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
// Need to create a data directory for all apps under this user.
installer.createUserData(ps.name,
- UserHandle.getUid(userHandle, ps.appId), userHandle);
+ UserHandle.getUid(userHandle, ps.appId), userHandle,
+ ps.pkg.applicationInfo.seinfo);
}
readDefaultPreferredAppsLPw(userHandle);
writePackageRestrictionsLPr(userHandle);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 0466c15473f5..d6dfff40844d 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -1514,7 +1514,11 @@ public class WindowManagerService extends IWindowManager.Stub
pos++;
}
if (pos >= N) {
- // All is good!
+ // Z order is good.
+ // The IM target window may be changed, so update the mTargetAppToken.
+ if (imWin != null) {
+ imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
+ }
return false;
}
}
@@ -9457,9 +9461,31 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_ORIENTATION &&
winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
TAG, "Resizing " + win + " WITH DRAW PENDING");
- win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets,
- winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING,
- configChanged ? win.mConfiguration : null);
+ final boolean reportDraw
+ = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
+ final Configuration newConfig = configChanged ? win.mConfiguration : null;
+ if (win.mClient instanceof IWindow.Stub) {
+ // Simulate one-way call if win.mClient is a local object.
+ final IWindow client = win.mClient;
+ final Rect frame = win.mFrame;
+ final Rect contentInsets = win.mLastContentInsets;
+ final Rect visibleInsets = win.mLastVisibleInsets;
+ mH.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ client.resized(frame, contentInsets, visibleInsets,
+ reportDraw, newConfig);
+ } catch (RemoteException e) {
+ // Actually, it's not a remote call.
+ // RemoteException mustn't be raised.
+ }
+ }
+ });
+ } else {
+ win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets,
+ reportDraw, newConfig);
+ }
win.mContentInsetsChanged = false;
win.mVisibleInsetsChanged = false;
winAnimator.mSurfaceResized = false;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 0f531b7a6b34..3cf48a0e183f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -111,9 +111,9 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
private void writePackagesList() {
writeFile(new File(getContext().getFilesDir(), "system/packages.list"),
- ( "com.google.app1 11000 0 /data/data/com.google.app1"
- + "com.google.app2 11001 0 /data/data/com.google.app2"
- + "com.android.app3 11030 0 /data/data/com.android.app3")
+ ( "com.google.app1 11000 0 /data/data/com.google.app1 seinfo1"
+ + "com.google.app2 11001 0 /data/data/com.google.app2 seinfo2"
+ + "com.android.app3 11030 0 /data/data/com.android.app3 seinfo3")
.getBytes());
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 03057777ab38..532148e00dec 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -1731,6 +1731,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
//Ignore more client requests
break;
case PEER_CONNECTION_USER_ACCEPT:
+ //Stop discovery to avoid failure due to channel switch
+ mWifiNative.p2pStopFind();
if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
mWifiNative.startWpsPbc(mGroup.getInterface(), null);
} else {