diff options
63 files changed, 1184 insertions, 548 deletions
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index 859d83b0abd6..74ccbc2b9220 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp @@ -15,10 +15,12 @@ #include <cutils/properties.h> #include <cutils/trace.h> #include <android_runtime/AndroidRuntime.h> +#include <private/android_filesystem_config.h> // for AID_SYSTEM #include <stdlib.h> #include <stdio.h> #include <unistd.h> +#include <sys/prctl.h> namespace android { @@ -136,6 +138,44 @@ static size_t computeArgBlockSize(int argc, char* const argv[]) { return (end - start); } +static void maybeCreateDalvikCache() { +#if defined(__aarch64__) + static const char kInstructionSet[] = "arm64"; +#elif defined(__x86_64__) + static const char kInstructionSet[] = "x86_64"; +#elif defined(__arm__) + static const char kInstructionSet[] = "arm"; +#elif defined(__i386__) + static const char kInstructionSet[] = "x86"; +#elif defined (__mips__) + static const char kInstructionSet[] = "mips"; +#else +#error "Unknown instruction set" +#endif + const char* androidRoot = getenv("ANDROID_DATA"); + LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset"); + + char dalvikCacheDir[PATH_MAX]; + const int numChars = snprintf(dalvikCacheDir, PATH_MAX, + "%s/dalvik-cache/%s", androidRoot, kInstructionSet); + LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0), + "Error constructing dalvik cache : %s", strerror(errno)); + + int result = mkdir(dalvikCacheDir, 0771); + LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST), + "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno)); + + // We always perform these steps because the directory might + // already exist, with wider permissions and a different owner + // than we'd like. + result = chown(dalvikCacheDir, AID_SYSTEM, AID_SYSTEM); + LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno)); + + result = chmod(dalvikCacheDir, 0771); + LOG_ALWAYS_FATAL_IF((result < 0), + "Error changing dalvik-cache permissions : %s", strerror(errno)); +} + #if defined(__LP64__) static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64"; static const char ZYGOTE_NICE_NAME[] = "zygote64"; @@ -146,6 +186,15 @@ static const char ZYGOTE_NICE_NAME[] = "zygote"; int main(int argc, char* const argv[]) { + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { + // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return + // EINVAL. Don't die on such kernels. + if (errno != EINVAL) { + LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno)); + return 12; + } + } + AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] @@ -213,13 +262,16 @@ int main(int argc, char* const argv[]) args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); } else { + // We're in zygote mode. + maybeCreateDalvikCache(); + if (startSystemServer) { args.add(String8("start-system-server")); } char prop[PROP_VALUE_MAX]; if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { - LOG_ALWAYS_FATAL("app_process: Unable to deterimine ABI list from property %s.", + LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", ABI_LIST_PROPERTY); return 11; } diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 1a2ab81badc3..7f7ae2c2f150 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -156,12 +156,12 @@ status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, return NO_ERROR; } -status_t BootAnimation::initTexture(void* buffer, size_t len) +status_t BootAnimation::initTexture(const Animation::Frame& frame) { //StopWatch watch("blah"); SkBitmap bitmap; - SkMemoryStream stream(buffer, len); + SkMemoryStream stream(frame.map->getDataPtr(), frame.map->getDataLength()); SkImageDecoder* codec = SkImageDecoder::Factory(&stream); if (codec) { codec->setDitherImage(false); @@ -171,6 +171,11 @@ status_t BootAnimation::initTexture(void* buffer, size_t len) delete codec; } + // FileMap memory is never released until application exit. + // Release it now as the texture is already loaded and the memory used for + // the packed resource can be released. + frame.map->release(); + // ensure we can call getPixels(). No need to call unlock, since the // bitmap will go out of scope when we return from this method. bitmap.lockPixels(); @@ -406,6 +411,7 @@ bool BootAnimation::movie() String8 desString((char const*)descMap->getDataPtr(), descMap->getDataLength()); + descMap->release(); char const* s = desString.string(); Animation animation; @@ -530,9 +536,7 @@ bool BootAnimation::movie() glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } - initTexture( - frame.map->getDataPtr(), - frame.map->getDataLength()); + initTexture(frame); } if (!clearReg.isEmpty()) { diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 22963c220b40..ba1c507d778c 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -79,7 +79,7 @@ private: }; status_t initTexture(Texture* texture, AssetManager& asset, const char* name); - status_t initTexture(void* buffer, size_t len); + status_t initTexture(const Animation::Frame& frame); bool android(); bool movie(); diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java index a292ecbf4df0..a8896c2cc59b 100644 --- a/core/java/android/app/SharedPreferencesImpl.java +++ b/core/java/android/app/SharedPreferencesImpl.java @@ -19,6 +19,9 @@ package android.app; import android.content.SharedPreferences; import android.os.FileUtils; import android.os.Looper; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import android.util.Log; import com.google.android.collect.Maps; @@ -44,10 +47,7 @@ import java.util.WeakHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; -import libcore.io.ErrnoException; import libcore.io.IoUtils; -import libcore.io.Libcore; -import libcore.io.StructStat; final class SharedPreferencesImpl implements SharedPreferences { private static final String TAG = "SharedPreferencesImpl"; @@ -111,7 +111,7 @@ final class SharedPreferencesImpl implements SharedPreferences { Map map = null; StructStat stat = null; try { - stat = Libcore.os.stat(mFile.getPath()); + stat = Os.stat(mFile.getPath()); if (mFile.canRead()) { BufferedInputStream str = null; try { @@ -173,7 +173,7 @@ final class SharedPreferencesImpl implements SharedPreferences { * violation, but we explicitly want this one. */ BlockGuard.getThreadPolicy().onReadFromDisk(); - stat = Libcore.os.stat(mFile.getPath()); + stat = Os.stat(mFile.getPath()); } catch (ErrnoException e) { return true; } @@ -600,7 +600,7 @@ final class SharedPreferencesImpl implements SharedPreferences { str.close(); ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0); try { - final StructStat stat = Libcore.os.stat(mFile.getPath()); + final StructStat stat = Os.stat(mFile.getPath()); synchronized (this) { mStatTimestamp = stat.st_mtime; mStatSize = stat.st_size; diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index ced72f80a029..c2bbff0e743a 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -668,6 +668,10 @@ public class WallpaperManager { * not "image/*" */ public Intent getCropAndSetWallpaperIntent(Uri imageUri) { + if (imageUri == null) { + throw new IllegalArgumentException("Image URI must not be null"); + } + if (!ContentResolver.SCHEME_CONTENT.equals(imageUri.getScheme())) { throw new IllegalArgumentException("Image URI must be of the " + ContentResolver.SCHEME_CONTENT + " scheme type"); diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 67c772bc0086..70a3797dd103 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -29,6 +29,10 @@ import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; +import android.system.StructStat; import android.util.Log; import java.io.File; @@ -38,11 +42,6 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.concurrent.CountDownLatch; -import libcore.io.ErrnoException; -import libcore.io.Libcore; -import libcore.io.OsConstants; -import libcore.io.StructStat; - /** * Provides the central interface between an * application and Android's data backup infrastructure. An application that wishes @@ -191,7 +190,7 @@ public abstract class BackupAgent extends ContextWrapper { * the key supplied as part of the entity. Writing an entity with a negative * data size instructs the transport to delete whatever entity currently exists * under that key from the remote data set. - * + * * @param oldState An open, read-only ParcelFileDescriptor pointing to the * last backup state provided by the application. May be * <code>null</code>, in which case no prior state is being @@ -222,7 +221,7 @@ public abstract class BackupAgent extends ContextWrapper { * onRestore() throws an exception, the OS will assume that the * application's data may now be in an incoherent state, and will clear it * before proceeding. - * + * * @param data A structured wrapper around an open, read-only * file descriptor pointing to a full snapshot of the * application's data. The application should consume every @@ -412,7 +411,7 @@ public abstract class BackupAgent extends ContextWrapper { } // If it's a directory, enqueue its contents for scanning. - StructStat stat = Libcore.os.lstat(filePath); + StructStat stat = Os.lstat(filePath); if (OsConstants.S_ISLNK(stat.st_mode)) { if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file); continue; diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index cb0737e3ad72..477285de8ec0 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java @@ -20,6 +20,8 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.ParcelFileDescriptor; +import android.system.ErrnoException; +import android.system.Os; import android.util.Log; import java.io.File; @@ -27,9 +29,6 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import libcore.io.ErrnoException; -import libcore.io.Libcore; - /** * Global constant definitions et cetera related to the full-backup-to-fd * binary format. Nothing in this namespace is part of any API; it's all @@ -150,7 +149,7 @@ public class FullBackup { try { // explicitly prevent emplacement of files accessible by outside apps mode &= 0700; - Libcore.os.chmod(outFile.getPath(), (int)mode); + Os.chmod(outFile.getPath(), (int)mode); } catch (ErrnoException e) { e.rethrowAsIOException(); } diff --git a/core/java/android/ddm/DdmHandleHeap.java b/core/java/android/ddm/DdmHandleHeap.java index cece556d6107..e24aeb2af3a1 100644 --- a/core/java/android/ddm/DdmHandleHeap.java +++ b/core/java/android/ddm/DdmHandleHeap.java @@ -219,7 +219,7 @@ public class DdmHandleHeap extends ChunkHandler { if (false) Log.d("ddm-heap", "Heap GC request"); - System.gc(); + Runtime.getRuntime().gc(); return null; // empty response } diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java index 22543e3ef156..a725becd74c6 100644 --- a/core/java/android/net/LinkAddress.java +++ b/core/java/android/net/LinkAddress.java @@ -24,13 +24,13 @@ import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.UnknownHostException; -import static libcore.io.OsConstants.IFA_F_DADFAILED; -import static libcore.io.OsConstants.IFA_F_DEPRECATED; -import static libcore.io.OsConstants.IFA_F_TENTATIVE; -import static libcore.io.OsConstants.RT_SCOPE_HOST; -import static libcore.io.OsConstants.RT_SCOPE_LINK; -import static libcore.io.OsConstants.RT_SCOPE_SITE; -import static libcore.io.OsConstants.RT_SCOPE_UNIVERSE; +import static android.system.OsConstants.IFA_F_DADFAILED; +import static android.system.OsConstants.IFA_F_DEPRECATED; +import static android.system.OsConstants.IFA_F_TENTATIVE; +import static android.system.OsConstants.RT_SCOPE_HOST; +import static android.system.OsConstants.RT_SCOPE_LINK; +import static android.system.OsConstants.RT_SCOPE_SITE; +import static android.system.OsConstants.RT_SCOPE_UNIVERSE; /** * Identifies an IP address on a network link. diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java index 119e5330f127..643e8c275035 100644 --- a/core/java/android/net/LocalSocketImpl.java +++ b/core/java/android/net/LocalSocketImpl.java @@ -22,9 +22,9 @@ import java.io.InputStream; import java.io.FileDescriptor; import java.net.SocketOptions; -import libcore.io.ErrnoException; -import libcore.io.Libcore; -import libcore.io.OsConstants; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; /** * Socket implementation used for android.net.LocalSocket and @@ -248,7 +248,7 @@ class LocalSocketImpl throw new IllegalStateException("unknown sockType"); } try { - fd = Libcore.os.socket(OsConstants.AF_UNIX, osType, 0); + fd = Os.socket(OsConstants.AF_UNIX, osType, 0); mFdCreatedInternally = true; } catch (ErrnoException e) { e.rethrowAsIOException(); @@ -268,7 +268,7 @@ class LocalSocketImpl return; } try { - Libcore.os.close(fd); + Os.close(fd); } catch (ErrnoException e) { e.rethrowAsIOException(); } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index c3313c53a5ee..1bddc7ade314 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -76,12 +76,38 @@ public class Build { public static final String SERIAL = getString("ro.serialno"); /** - * A list of ABIs (in priority) order supported by this device. + * An ordered list of ABIs supported by this device. The most preferred ABI is the first + * element in the list. + * + * See {@link #SUPPORTED_32_BIT_ABIS} and {@link #SUPPORTED_64_BIT_ABIS}. * * @hide */ public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").split(","); + /** + * An ordered list of <b>32 bit</b> ABIs supported by this device. The most preferred ABI + * is the first element in the list. + * + * See {@link #SUPPORTED_ABIS} and {@link #SUPPORTED_64_BIT_ABIS}. + * + * @hide + */ + public static final String[] SUPPORTED_32_BIT_ABIS = getString("ro.product.cpu.abilist32") + .split(","); + + /** + * An ordered list of <b>64 bit</b> ABIs supported by this device. The most preferred ABI + * is the first element in the list. + * + * See {@link #SUPPORTED_ABIS} and {@link #SUPPORTED_32_BIT_ABIS}. + * + * @hide + */ + public static final String[] SUPPORTED_64_BIT_ABIS = getString("ro.product.cpu.abilist64") + .split(","); + + /** Various version strings. */ public static class VERSION { /** diff --git a/core/java/android/os/CommonClock.java b/core/java/android/os/CommonClock.java index 3a1da9761b6b..7f41c5d98e9b 100644 --- a/core/java/android/os/CommonClock.java +++ b/core/java/android/os/CommonClock.java @@ -20,7 +20,6 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetSocketAddress; import java.util.NoSuchElementException; -import static libcore.io.OsConstants.*; import android.content.ComponentName; import android.content.Context; @@ -32,6 +31,7 @@ import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; +import static android.system.OsConstants.*; /** * Used for accessing the android common time service's common clock and receiving notifications diff --git a/core/java/android/os/CommonTimeUtils.java b/core/java/android/os/CommonTimeUtils.java index 20755d92d2d5..ba060b87567e 100644 --- a/core/java/android/os/CommonTimeUtils.java +++ b/core/java/android/os/CommonTimeUtils.java @@ -20,7 +20,7 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetSocketAddress; import java.util.Locale; -import static libcore.io.OsConstants.*; +import static android.system.OsConstants.*; class CommonTimeUtils { /** diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index b5413db04b70..7bf73673cb6c 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -42,6 +42,8 @@ public class Environment { private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE"; private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE"; private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT"; + private static final String ENV_OEM_ROOT = "OEM_ROOT"; + private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT"; /** {@hide} */ public static final String DIR_ANDROID = "Android"; @@ -56,6 +58,8 @@ public class Environment { public static final String DIRECTORY_ANDROID = DIR_ANDROID; private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system"); + private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem"); + private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor"); private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media"); private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull( @@ -244,6 +248,25 @@ public class Environment { } /** + * Return root directory of the "oem" partition holding OEM customizations, + * if any. If present, the partition is mounted read-only. + * + * @hide + */ + public static File getOemDirectory() { + return DIR_OEM_ROOT; + } + + /** + * Return root directory of the "vendor" partition that holds vendor-provided + * software that should persist across simple reflashing of the "system" partition. + * @hide + */ + public static File getVendorDirectory() { + return DIR_VENDOR_ROOT; + } + + /** * Gets the system directory available for secure storage. * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system). * Otherwise, it returns the unencrypted /data/system directory. diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index ff3e27785b74..3e0b54a4d2cf 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -16,13 +16,13 @@ package android.os; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; import android.util.Log; import android.util.Slog; -import libcore.io.ErrnoException; import libcore.io.IoUtils; -import libcore.io.Libcore; -import libcore.io.OsConstants; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; @@ -87,7 +87,7 @@ public class FileUtils { */ public static int setPermissions(String path, int mode, int uid, int gid) { try { - Libcore.os.chmod(path, mode); + Os.chmod(path, mode); } catch (ErrnoException e) { Slog.w(TAG, "Failed to chmod(" + path + "): " + e); return e.errno; @@ -95,7 +95,7 @@ public class FileUtils { if (uid >= 0 || gid >= 0) { try { - Libcore.os.chown(path, uid, gid); + Os.chown(path, uid, gid); } catch (ErrnoException e) { Slog.w(TAG, "Failed to chown(" + path + "): " + e); return e.errno; @@ -115,7 +115,7 @@ public class FileUtils { */ public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) { try { - Libcore.os.fchmod(fd, mode); + Os.fchmod(fd, mode); } catch (ErrnoException e) { Slog.w(TAG, "Failed to fchmod(): " + e); return e.errno; @@ -123,7 +123,7 @@ public class FileUtils { if (uid >= 0 || gid >= 0) { try { - Libcore.os.fchown(fd, uid, gid); + Os.fchown(fd, uid, gid); } catch (ErrnoException e) { Slog.w(TAG, "Failed to fchown(): " + e); return e.errno; @@ -138,7 +138,7 @@ public class FileUtils { */ public static int getUid(String path) { try { - return Libcore.os.stat(path).st_uid; + return Os.stat(path).st_uid; } catch (ErrnoException e) { return -1; } @@ -357,4 +357,26 @@ public class FileUtils { } } } + + /** + * Test if a file lives under the given directory, either as a direct child + * or a distant grandchild. + * <p> + * Both files <em>must</em> have been resolved using + * {@link File#getCanonicalFile()} to avoid symlink or path traversal + * attacks. + */ + public static boolean contains(File dir, File file) { + String dirPath = dir.getAbsolutePath(); + String filePath = file.getAbsolutePath(); + + if (dirPath.equals(filePath)) { + return true; + } + + if (!dirPath.endsWith("/")) { + dirPath += "/"; + } + return filePath.startsWith(dirPath); + } } diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 5273c20abf9d..59795da92669 100644 --- a/core/java/android/os/ParcelFileDescriptor.java +++ b/core/java/android/os/ParcelFileDescriptor.java @@ -16,24 +16,24 @@ package android.os; -import static libcore.io.OsConstants.AF_UNIX; -import static libcore.io.OsConstants.SEEK_SET; -import static libcore.io.OsConstants.SOCK_STREAM; -import static libcore.io.OsConstants.S_ISLNK; -import static libcore.io.OsConstants.S_ISREG; +import static android.system.OsConstants.AF_UNIX; +import static android.system.OsConstants.SEEK_SET; +import static android.system.OsConstants.SOCK_STREAM; +import static android.system.OsConstants.S_ISLNK; +import static android.system.OsConstants.S_ISREG; import android.content.BroadcastReceiver; import android.content.ContentProvider; +import android.system.ErrnoException; +import android.system.Os; +import android.system.OsConstants; +import android.system.StructStat; import android.util.Log; import dalvik.system.CloseGuard; -import libcore.io.ErrnoException; import libcore.io.IoUtils; -import libcore.io.Libcore; import libcore.io.Memory; -import libcore.io.OsConstants; -import libcore.io.StructStat; import java.io.Closeable; import java.io.File; @@ -42,6 +42,7 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InterruptedIOException; import java.net.DatagramSocket; import java.net.Socket; import java.nio.ByteOrder; @@ -260,7 +261,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { */ public static ParcelFileDescriptor dup(FileDescriptor orig) throws IOException { try { - final FileDescriptor fd = Libcore.os.dup(orig); + final FileDescriptor fd = Os.dup(orig); return new ParcelFileDescriptor(fd); } catch (ErrnoException e) { throw e.rethrowAsIOException(); @@ -296,7 +297,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { original.setInt$(fd); try { - final FileDescriptor dup = Libcore.os.dup(original); + final FileDescriptor dup = Os.dup(original); return new ParcelFileDescriptor(dup); } catch (ErrnoException e) { throw e.rethrowAsIOException(); @@ -358,7 +359,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { */ public static ParcelFileDescriptor[] createPipe() throws IOException { try { - final FileDescriptor[] fds = Libcore.os.pipe(); + final FileDescriptor[] fds = Os.pipe(); return new ParcelFileDescriptor[] { new ParcelFileDescriptor(fds[0]), new ParcelFileDescriptor(fds[1]) }; @@ -380,7 +381,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { public static ParcelFileDescriptor[] createReliablePipe() throws IOException { try { final FileDescriptor[] comm = createCommSocketPair(); - final FileDescriptor[] fds = Libcore.os.pipe(); + final FileDescriptor[] fds = Os.pipe(); return new ParcelFileDescriptor[] { new ParcelFileDescriptor(fds[0], comm[0]), new ParcelFileDescriptor(fds[1], comm[1]) }; @@ -397,7 +398,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { try { final FileDescriptor fd0 = new FileDescriptor(); final FileDescriptor fd1 = new FileDescriptor(); - Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1); + Os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1); return new ParcelFileDescriptor[] { new ParcelFileDescriptor(fd0), new ParcelFileDescriptor(fd1) }; @@ -420,7 +421,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { final FileDescriptor[] comm = createCommSocketPair(); final FileDescriptor fd0 = new FileDescriptor(); final FileDescriptor fd1 = new FileDescriptor(); - Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1); + Os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1); return new ParcelFileDescriptor[] { new ParcelFileDescriptor(fd0, comm[0]), new ParcelFileDescriptor(fd1, comm[1]) }; @@ -433,7 +434,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { try { final FileDescriptor comm1 = new FileDescriptor(); final FileDescriptor comm2 = new FileDescriptor(); - Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2); + Os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2); IoUtils.setBlocking(comm1, false); IoUtils.setBlocking(comm2, false); return new FileDescriptor[] { comm1, comm2 }; @@ -519,7 +520,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { return mWrapped.getStatSize(); } else { try { - final StructStat st = Libcore.os.fstat(mFd); + final StructStat st = Os.fstat(mFd); if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { return st.st_size; } else { @@ -542,7 +543,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { return mWrapped.seekTo(pos); } else { try { - return Libcore.os.lseek(mFd, pos, SEEK_SET); + return Os.lseek(mFd, pos, SEEK_SET); } catch (ErrnoException e) { throw e.rethrowAsIOException(); } @@ -694,10 +695,13 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { writePtr += len; } - Libcore.os.write(mCommFd, buf, 0, writePtr); + Os.write(mCommFd, buf, 0, writePtr); } catch (ErrnoException e) { // Reporting status is best-effort Log.w(TAG, "Failed to report status: " + e); + } catch (InterruptedIOException e) { + // Reporting status is best-effort + Log.w(TAG, "Failed to report status: " + e); } } finally { @@ -708,7 +712,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { private static Status readCommStatus(FileDescriptor comm, byte[] buf) { try { - final int n = Libcore.os.read(comm, buf, 0, buf.length); + final int n = Os.read(comm, buf, 0, buf.length); if (n == 0) { // EOF means they're dead return new Status(Status.DEAD); @@ -728,6 +732,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable { Log.d(TAG, "Failed to read status; assuming dead: " + e); return new Status(Status.DEAD); } + } catch (InterruptedIOException e) { + Log.d(TAG, "Failed to read status; assuming dead: " + e); + return new Status(Status.DEAD); } } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 96f42ccdeaa7..a4c4a879b4a5 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -18,6 +18,7 @@ package android.os; import android.net.LocalSocket; import android.net.LocalSocketAddress; +import android.system.Os; import android.util.Log; import com.android.internal.os.Zygote; import java.io.BufferedWriter; @@ -28,7 +29,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import libcore.io.Libcore; /*package*/ class ZygoteStartFailedEx extends Exception { /** @@ -707,16 +707,6 @@ public class Process { return primaryZygoteState; } - // TODO: Get rid of this. This is a temporary workaround until all the - // compilation related pieces for the dual zygote stack are ready. - // b/3647418. - if (System.getenv("ANDROID_SOCKET_" + SECONDARY_ZYGOTE_SOCKET) == null) { - Log.e(LOG_TAG, "Forcing app to primary zygote, secondary unavailable (ABI= " + abi + ")"); - // Should be : - // throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); - return primaryZygoteState; - } - // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET, @@ -741,7 +731,7 @@ public class Process { * {@link #killProcess} and {@link #sendSignal}. */ public static final int myPid() { - return Libcore.os.getpid(); + return Os.getpid(); } /** @@ -749,7 +739,7 @@ public class Process { * @hide */ public static final int myPpid() { - return Libcore.os.getppid(); + return Os.getppid(); } /** @@ -757,7 +747,7 @@ public class Process { * {@link #setThreadPriority(int, int)}. */ public static final int myTid() { - return Libcore.os.gettid(); + return Os.gettid(); } /** @@ -767,7 +757,7 @@ public class Process { * a uid identifies a specific app sandbox in a specific user. */ public static final int myUid() { - return Libcore.os.getuid(); + return Os.getuid(); } /** diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java index 9e9521a2dbcc..13e9a15eedb6 100644 --- a/core/java/android/os/StatFs.java +++ b/core/java/android/os/StatFs.java @@ -16,9 +16,9 @@ package android.os; -import libcore.io.ErrnoException; -import libcore.io.Libcore; -import libcore.io.StructStatVfs; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStatVfs; /** * Retrieve overall information about the space on a filesystem. This is a @@ -41,7 +41,7 @@ public class StatFs { private static StructStatVfs doStat(String path) { try { - return Libcore.os.statvfs(path); + return Os.statvfs(path); } catch (ErrnoException e) { throw new IllegalArgumentException("Invalid path: " + path, e); } diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 86d3cf864a42..39775b625dc4 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -17,7 +17,7 @@ package android.provider; import static android.net.TrafficStats.KB_IN_BYTES; -import static libcore.io.OsConstants.SEEK_SET; +import static android.system.OsConstants.SEEK_SET; import android.content.ContentProviderClient; import android.content.ContentResolver; @@ -38,11 +38,11 @@ import android.os.OperationCanceledException; import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor.OnCloseListener; import android.os.RemoteException; +import android.system.ErrnoException; +import android.system.Os; import android.util.Log; -import libcore.io.ErrnoException; import libcore.io.IoUtils; -import libcore.io.Libcore; import java.io.BufferedInputStream; import java.io.File; @@ -699,7 +699,7 @@ public final class DocumentsContract { // optimal decode path; otherwise fall back to buffering. BufferedInputStream is = null; try { - Libcore.os.lseek(fd, offset, SEEK_SET); + Os.lseek(fd, offset, SEEK_SET); } catch (ErrnoException e) { is = new BufferedInputStream(new FileInputStream(fd), THUMBNAIL_BUFFER_SIZE); is.mark(THUMBNAIL_BUFFER_SIZE); @@ -725,7 +725,7 @@ public final class DocumentsContract { bitmap = BitmapFactory.decodeStream(is, null, opts); } else { try { - Libcore.os.lseek(fd, offset, SEEK_SET); + Os.lseek(fd, offset, SEEK_SET); } catch (ErrnoException e) { e.rethrowAsIOException(); } diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index 29c0ba2f3008..aefced8a6260 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -56,16 +56,18 @@ public class EventLog { public static final class Event { private final ByteBuffer mBuffer; - // Layout of event log entry received from kernel. + // Layout of event log entry received from Android logger. + // see system/core/include/log/logger.h private static final int LENGTH_OFFSET = 0; + private static final int HEADER_SIZE_OFFSET = 2; private static final int PROCESS_OFFSET = 4; private static final int THREAD_OFFSET = 8; private static final int SECONDS_OFFSET = 12; private static final int NANOSECONDS_OFFSET = 16; - private static final int PAYLOAD_START = 20; - private static final int TAG_OFFSET = 20; - private static final int DATA_START = 24; + // Layout for event log v1 format, v2 and v3 use HEADER_SIZE_OFFSET + private static final int V1_PAYLOAD_START = 20; + private static final int DATA_OFFSET = 4; // Value types private static final byte INT_TYPE = 0; @@ -97,14 +99,22 @@ public class EventLog { /** @return the type tag code of the entry */ public int getTag() { - return mBuffer.getInt(TAG_OFFSET); + int offset = mBuffer.getShort(HEADER_SIZE_OFFSET); + if (offset == 0) { + offset = V1_PAYLOAD_START; + } + return mBuffer.getInt(offset); } /** @return one of Integer, Long, String, null, or Object[] of same. */ public synchronized Object getData() { try { - mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET)); - mBuffer.position(DATA_START); // Just after the tag. + int offset = mBuffer.getShort(HEADER_SIZE_OFFSET); + if (offset == 0) { + offset = V1_PAYLOAD_START; + } + mBuffer.limit(offset + mBuffer.getShort(LENGTH_OFFSET)); + mBuffer.position(offset + DATA_OFFSET); // Just after the tag. return decodeObject(); } catch (IllegalArgumentException e) { Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3fd2aa9de924..0f633a05a7c4 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -674,6 +674,11 @@ public final class ViewRootImpl implements ViewParent, } } + public boolean invokeFunctor(long functor, boolean waitForCompletion) { + // stub + return false; + } + private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) { mAttachInfo.mHardwareAccelerated = false; mAttachInfo.mHardwareAccelerationRequested = false; diff --git a/core/java/android/webkit/ClientCertRequest.java b/core/java/android/webkit/ClientCertRequest.java new file mode 100644 index 000000000000..89517863d212 --- /dev/null +++ b/core/java/android/webkit/ClientCertRequest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import java.security.Principal; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +/** + * ClientCertRequest: The user receives an instance of this class as + * a parameter of {@link WebViewClient#onReceivedClientCertRequest}. + * The request includes the parameters to choose the client certificate, + * such as the host name and the port number requesting the cert, the acceptable + * key types and the principals. + * + * The user should call one of the interface methods to indicate how to deal + * with the client certificate request. All methods should be called on + * UI thread. + * + * WebView caches the {@link #proceed} and {@link #cancel} responses in memory + * and uses them to handle future client certificate requests for the same + * host/port pair. The user can clear the cached data using + * {@link WebView#clearClientCertPreferences}. + * + * TODO(sgurun) unhide + * @hide + */ +public interface ClientCertRequest { + /** + * Returns the acceptable types of asymmetric keys (can be null). + */ + public String[] getKeyTypes(); + + /** + * Returns the acceptable certificate issuers for the certificate + * matching the private key (can be null). + */ + public Principal[] getPrincipals(); + + /** + * Returns the host name of the server requesting the certificate. + */ + public String getHost(); + + /** + * Returns the port number of the server requesting the certificate. + */ + public int getPort(); + + /** + * Proceed with the specified private key and client certificate chain. + * Remember the user's positive choice and use it for future requests. + */ + public void proceed(PrivateKey privateKey, X509Certificate[] chain); + + /** + * Ignore the request for now. Do not remember user's choice. + */ + public void ignore(); + + /** + * Cancel this request. Remember the user's choice and use it for + * future requests. + */ + public void cancel(); +} diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index e8974c6cda33..fb842ff9b502 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -204,6 +204,30 @@ public class WebViewClient { handler.cancel(); } + /** + * Notify the host application to handle a SSL client certificate + * request. The host application is responsible for showing the UI + * if desired and providing the keys. There are three ways to + * respond: proceed(), cancel() or ignore(). Webview remembers the + * response if proceed() or cancel() is called and does not + * call onReceivedClientCertRequest() again for the same host and port + * pair. Webview does not remember the response if ignore() is called. + * + * This method is called on the UI thread. During the callback, the + * connection is suspended. + * + * The default behavior is to cancel, returning no client certificate. + * + * @param view The WebView that is initiating the callback + * @param request An instance of a {@link ClientCertRequest} + * + * TODO(sgurun) unhide + * @hide + */ + public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) { + request.cancel(); + } + /** * Notifies the host application that the WebView received an HTTP * authentication request. The host application can use the supplied diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index c5fa0a1a5ab2..54c532abd090 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -18,8 +18,8 @@ package com.android.internal.os; import dalvik.system.ZygoteHooks; -import libcore.io.ErrnoException; -import libcore.io.Libcore; +import android.system.ErrnoException; +import android.system.Os; /** @hide */ public final class Zygote { @@ -141,7 +141,7 @@ public final class Zygote { public static void execShell(String command) { String[] args = { "/system/bin/sh", "-c", command }; try { - Libcore.os.execv(args[0], args); + Os.execv(args[0], args); } catch (ErrnoException e) { throw new RuntimeException(e); } diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 58a8e622e699..0c4836854ace 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -21,6 +21,8 @@ import android.net.LocalSocket; import android.os.Process; import android.os.SELinux; import android.os.SystemProperties; +import android.system.ErrnoException; +import android.system.Os; import android.util.Log; import dalvik.system.PathClassLoader; import java.io.BufferedReader; @@ -34,9 +36,7 @@ import java.io.InputStreamReader; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import libcore.io.ErrnoException; import libcore.io.IoUtils; -import libcore.io.Libcore; /** * A connection that can make spawn requests. @@ -186,7 +186,7 @@ class ZygoteConnection { } if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) { - FileDescriptor[] pipeFds = Libcore.os.pipe(); + FileDescriptor[] pipeFds = Os.pipe(); childPipeFd = pipeFds[1]; serverPipeFd = pipeFds[0]; ZygoteInit.setCloseOnExec(serverPipeFd, true); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 495cc5fd8b4b..bee1391b534e 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -16,8 +16,8 @@ package com.android.internal.os; -import static libcore.io.OsConstants.S_IRWXG; -import static libcore.io.OsConstants.S_IRWXO; +import static android.system.OsConstants.S_IRWXG; +import static android.system.OsConstants.S_IRWXO; import android.content.res.Resources; import android.content.res.TypedArray; @@ -28,14 +28,14 @@ import android.os.Process; import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; +import android.system.Os; +import android.system.OsConstants; import android.util.EventLog; import android.util.Log; import dalvik.system.VMRuntime; import libcore.io.IoUtils; -import libcore.io.Libcore; -import libcore.io.OsConstants; import java.io.BufferedReader; import java.io.FileDescriptor; @@ -473,7 +473,7 @@ public class ZygoteInit { closeServerSocket(); // set umask to 0077 so new files and directories will default to owner-only permissions. - Libcore.os.umask(S_IRWXG | S_IRWXO); + Os.umask(S_IRWXG | S_IRWXO); if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); @@ -499,6 +499,7 @@ public class ZygoteInit { private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( + OsConstants.CAP_BLOCK_SUSPEND, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp index 799782d53ce2..6591d60b1eec 100644 --- a/core/jni/android/graphics/YuvToJpegEncoder.cpp +++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp @@ -226,16 +226,17 @@ static jboolean YuvImage_compressToJpeg(JNIEnv* env, jobject, jbyteArray inYuv, jint* imgOffsets = env->GetIntArrayElements(offsets, NULL); jint* imgStrides = env->GetIntArrayElements(strides, NULL); YuvToJpegEncoder* encoder = YuvToJpegEncoder::create(format, imgStrides); - if (encoder == NULL) { - return JNI_FALSE; + jboolean result = JNI_FALSE; + if (encoder != NULL) { + encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality); + delete encoder; + result = JNI_TRUE; } - encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality); - delete encoder; env->ReleaseByteArrayElements(inYuv, yuv, 0); env->ReleaseIntArrayElements(offsets, imgOffsets, 0); env->ReleaseIntArrayElements(strides, imgStrides, 0); - return JNI_TRUE; + return result; } /////////////////////////////////////////////////////////////////////////////// diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 9f8eb34c6209..31876ce52533 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -30,15 +30,16 @@ #include "android_util_Binder.h" #include "JNIHelp.h" -#include <sys/errno.h> -#include <sys/resource.h> -#include <sys/types.h> -#include <sys/stat.h> #include <dirent.h> #include <fcntl.h> #include <grp.h> +#include <inttypes.h> #include <pwd.h> #include <signal.h> +#include <sys/errno.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> #define POLICY_DEBUG 0 @@ -159,7 +160,7 @@ jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name) void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint grp) { - ALOGV("%s tid=%d grp=%d", __func__, tid, grp); + ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp); SchedPolicy sp = (SchedPolicy) grp; int res = set_sched_policy(tid, sp); if (res != NO_ERROR) { @@ -169,7 +170,7 @@ void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp) { - ALOGV("%s pid=%d grp=%d", __func__, pid, grp); + ALOGV("%s pid=%d grp=%" PRId32, __func__, pid, grp); DIR *d; FILE *fp; char proc_path[255]; @@ -322,7 +323,7 @@ void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz, } } - //ALOGI("Setting priority of %d: %d, getpriority returns %d\n", + //ALOGI("Setting priority of %" PRId32 ": %" PRId32 ", getpriority returns %d\n", // pid, pri, getpriority(PRIO_PROCESS, pid)); } @@ -340,7 +341,7 @@ jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz, if (errno != 0) { signalExceptionForPriorityError(env, errno); } - //ALOGI("Returning priority of %d: %d\n", pid, pri); + //ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri); return pri; } @@ -379,7 +380,7 @@ jboolean android_os_Process_setSwappiness(JNIEnv *env, jobject clazz, int fd = open(text, O_WRONLY); if (fd >= 0) { - sprintf(text, "%d", pid); + sprintf(text, "%" PRId32, pid); write(fd, text, strlen(text)); close(fd); } @@ -420,7 +421,7 @@ jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint uid) static int pid_compare(const void* v1, const void* v2) { - //ALOGI("Compare %d vs %d\n", *((const jint*)v1), *((const jint*)v2)); + //ALOGI("Compare %" PRId32 " vs %" PRId32 "\n", *((const jint*)v1), *((const jint*)v2)); return *((const jint*)v1) - *((const jint*)v2); } @@ -534,7 +535,7 @@ void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileSt return; } - //ALOGI("Clearing %d sizes", count); + //ALOGI("Clearing %" PRId32 " sizes", count); for (i=0; i<count; i++) { sizesArray[i] = 0; } @@ -573,7 +574,7 @@ void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileSt } char* end; sizesArray[i] = strtoll(num, &end, 10); - //ALOGI("Field %s = %d", field.string(), sizesArray[i]); + //ALOGI("Field %s = %" PRId64, field.string(), sizesArray[i]); foundCount++; break; } @@ -775,7 +776,7 @@ jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz, } } - //ALOGI("Field %d: %d-%d dest=%d mode=0x%x\n", i, start, end, di, mode); + //ALOGI("Field %" PRId32 ": %" PRId32 "-%" PRId32 " dest=%" PRId32 " mode=0x%" PRIx32 "\n", i, start, end, di, mode); if ((mode&(PROC_OUT_FLOAT|PROC_OUT_LONG|PROC_OUT_STRING)) != 0) { char c = buffer[end]; @@ -874,7 +875,7 @@ void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz, void android_os_Process_sendSignal(JNIEnv* env, jobject clazz, jint pid, jint sig) { if (pid > 0) { - ALOGI("Sending signal. PID: %d SIG: %d", pid, sig); + ALOGI("Sending signal. PID: %" PRId32 " SIG: %" PRId32, pid, sig); kill(pid, sig); } } @@ -904,7 +905,7 @@ static jlong android_os_Process_getPss(JNIEnv* env, jobject clazz, jint pid) { char filename[64]; - snprintf(filename, sizeof(filename), "/proc/%d/smaps", pid); + snprintf(filename, sizeof(filename), "/proc/%" PRId32 "/smaps", pid); FILE * file = fopen(filename, "r"); if (!file) { @@ -916,7 +917,7 @@ static jlong android_os_Process_getPss(JNIEnv* env, jobject clazz, jint pid) jlong pss = 0; while (fgets(line, sizeof(line), file)) { jlong v; - if (sscanf(line, "Pss: %lld kB", &v) == 1) { + if (sscanf(line, "Pss: %" SCNd64 " kB", &v) == 1) { pss += v; } } diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index a61fa874beb6..c58bf04f1f4e 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -92,14 +92,10 @@ static void SigChldHandler(int /*signal_number*/) { if (WIFEXITED(status)) { if (WEXITSTATUS(status)) { ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status)); - } else if (false) { - ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status)); } } else if (WIFSIGNALED(status)) { if (WTERMSIG(status) != SIGKILL) { - ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status)); - } else if (false) { - ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status)); + ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status)); } #ifdef WCOREDUMP if (WCOREDUMP(status)) { @@ -117,8 +113,10 @@ static void SigChldHandler(int /*signal_number*/) { } } - if (pid < 0) { - ALOGW("Zygote SIGCHLD error in waitpid: %d", errno); + // Note that we shouldn't consider ECHILD an error because + // the secondary zygote might have no children left to wait for. + if (pid < 0 && errno != ECHILD) { + ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno)); } } diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 04f8009a40d5..84b56cee6f92 100644 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -16,7 +16,7 @@ package android.content.pm; -import static libcore.io.OsConstants.*; +import static android.system.OsConstants.*; import com.android.frameworks.coretests.R; import com.android.internal.content.PackageHelper; @@ -46,6 +46,9 @@ import android.os.storage.StorageManager; import android.os.storage.StorageResultCode; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.SmallTest; @@ -60,10 +63,6 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import libcore.io.ErrnoException; -import libcore.io.Libcore; -import libcore.io.StructStat; - public class PackageManagerTests extends AndroidTestCase { private static final boolean localLOGV = true; @@ -501,7 +500,7 @@ public class PackageManagerTests extends AndroidTestCase { final StructStat stat; try { - stat = Libcore.os.lstat(path); + stat = Os.lstat(path); } catch (ErrnoException e) { throw new AssertionError(reason + "\n" + "Got: " + path + " does not exist"); } diff --git a/core/tests/coretests/src/android/net/LinkAddressTest.java b/core/tests/coretests/src/android/net/LinkAddressTest.java index 17423be65feb..bccf5564869c 100644 --- a/core/tests/coretests/src/android/net/LinkAddressTest.java +++ b/core/tests/coretests/src/android/net/LinkAddressTest.java @@ -32,13 +32,13 @@ import android.os.Parcel; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; -import static libcore.io.OsConstants.IFA_F_DEPRECATED; -import static libcore.io.OsConstants.IFA_F_PERMANENT; -import static libcore.io.OsConstants.IFA_F_TENTATIVE; -import static libcore.io.OsConstants.RT_SCOPE_HOST; -import static libcore.io.OsConstants.RT_SCOPE_LINK; -import static libcore.io.OsConstants.RT_SCOPE_SITE; -import static libcore.io.OsConstants.RT_SCOPE_UNIVERSE; +import static android.system.OsConstants.IFA_F_DEPRECATED; +import static android.system.OsConstants.IFA_F_PERMANENT; +import static android.system.OsConstants.IFA_F_TENTATIVE; +import static android.system.OsConstants.RT_SCOPE_HOST; +import static android.system.OsConstants.RT_SCOPE_LINK; +import static android.system.OsConstants.RT_SCOPE_SITE; +import static android.system.OsConstants.RT_SCOPE_UNIVERSE; /** * Tests for {@link LinkAddress}. diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java index a602e07d9b04..553afe0d6931 100644 --- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java +++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java @@ -18,14 +18,13 @@ package android.net; import android.net.LinkProperties; import android.net.RouteInfo; +import android.system.OsConstants; import android.test.suitebuilder.annotation.SmallTest; import junit.framework.TestCase; import java.net.InetAddress; import java.util.ArrayList; -import libcore.io.OsConstants; - public class LinkPropertiesTest extends TestCase { private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1"); private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress( diff --git a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java index 0e3c13a0e655..3f9e62e7b180 100644 --- a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java +++ b/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java @@ -46,7 +46,6 @@ import java.util.Random; import junit.framework.Assert; import libcore.io.IoUtils; -import libcore.io.Libcore; /** * Tests for {@link FileRotator}. diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl index 1413319c2fd0..ecd6a8bf3cfe 100644 --- a/data/keyboards/Generic.kl +++ b/data/keyboards/Generic.kl @@ -404,6 +404,8 @@ key 484 B FUNCTION # key 503 KEY_BRL_DOT7 # key 504 KEY_BRL_DOT8 +key 580 APP_SWITCH + # Keys defined by HID usages key usage 0x0c006F BRIGHTNESS_UP key usage 0x0c0070 BRIGHTNESS_DOWN diff --git a/include/private/hwui/DrawGlInfo.h b/include/private/hwui/DrawGlInfo.h index fc810be8dc62..236e64c325e2 100644 --- a/include/private/hwui/DrawGlInfo.h +++ b/include/private/hwui/DrawGlInfo.h @@ -55,7 +55,8 @@ struct DrawGlInfo { kModeDraw, // Indicates the the functor is called only to perform // processing and that no draw should be attempted - kModeProcess + kModeProcess, + kModeProcessNoContext }; /** diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 0be17ff868b4..8d19ca2b8f99 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -735,30 +735,34 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int // a null path is OK because there are no custom kernels used // hence nothing gets cached by RS if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) { + mRs.clear(); ALOGE("blur RS failed to init"); + } else { + mRsElement = RSC::Element::A_8(mRs); + mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement); } - - mRsElement = RSC::Element::A_8(mRs); - mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement); } + if (mRs != 0) { + RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0); + RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t, + RS_ALLOCATION_MIPMAP_NONE, + RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, + *image); + RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t, + RS_ALLOCATION_MIPMAP_NONE, + RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, + outImage); + + mRsScript->setRadius(radius); + mRsScript->setInput(ain); + mRsScript->forEach(aout); + + // replace the original image's pointer, avoiding a copy back to the original buffer + free(*image); + *image = outImage; - RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0); - RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t, - RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, - *image); - RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t, - RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, - outImage); - - mRsScript->setRadius(radius); - mRsScript->setInput(ain); - mRsScript->forEach(aout); - - // replace the original image's pointer, avoiding a copy back to the original buffer - free(*image); - *image = outImage; - - return; + return; + } } #endif diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 53835e2dbeb2..06a8f4c247cd 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -44,6 +44,8 @@ import android.provider.Settings; import android.sax.Element; import android.sax.ElementListener; import android.sax.RootElement; +import android.system.ErrnoException; +import android.system.Os; import android.text.TextUtils; import android.util.Log; import android.util.Xml; @@ -59,9 +61,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Locale; -import libcore.io.ErrnoException; -import libcore.io.Libcore; - /** * Internal service helper that no-one should use directly. * @@ -1129,7 +1128,7 @@ public class MediaScanner if (path != null && path.startsWith("/")) { boolean exists = false; try { - exists = Libcore.os.access(path, libcore.io.OsConstants.F_OK); + exists = Os.access(path, android.system.OsConstants.F_OK); } catch (ErrnoException e1) { } if (!exists && !MtpConstants.isAbstractObject(format)) { @@ -1280,6 +1279,14 @@ public class MediaScanner mMediaProvider = null; } + private void releaseResources() { + // release the DrmManagerClient resources + if (mDrmManagerClient != null) { + mDrmManagerClient.release(); + mDrmManagerClient = null; + } + } + private void initialize(String volumeName) { mMediaProvider = mContext.getContentResolver().acquireProvider("media"); @@ -1340,6 +1347,8 @@ public class MediaScanner Log.e(TAG, "UnsupportedOperationException in MediaScanner.scan()", e); } catch (RemoteException e) { Log.e(TAG, "RemoteException in MediaScanner.scan()", e); + } finally { + releaseResources(); } } @@ -1363,6 +1372,8 @@ public class MediaScanner } catch (RemoteException e) { Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e); return null; + } finally { + releaseResources(); } } @@ -1477,6 +1488,7 @@ public class MediaScanner if (fileList != null) { fileList.close(); } + releaseResources(); } } diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 221ea57f8ed8..5fd5dee6b2c7 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -192,7 +192,7 @@ status_t JMediaCodec::dequeueOutputBuffer( env, env->FindClass("android/media/MediaCodec$BufferInfo")); jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V"); - env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags); + env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags); return OK; } diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp index 6176f0f1f2b1..c2694f1fb9cb 100644 --- a/media/jni/android_media_MediaMetadataRetriever.cpp +++ b/media/jni/android_media_MediaMetadataRetriever.cpp @@ -262,6 +262,13 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, width, height, config); + if (jBitmap == NULL) { + if (env->ExceptionCheck()) { + env->ExceptionClear(); + } + ALOGE("getFrameAtTime: create Bitmap failed!"); + return NULL; + } SkBitmap *bitmap = (SkBitmap *) env->GetLongField(jBitmap, fields.nativeBitmap); diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 5a2e261fa3a4..4c024aeb0303 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -882,7 +882,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback protected int[] mConfigSpec; private int[] filterConfigSpec(int[] configSpec) { - if (mEGLContextClientVersion != 2) { + if (mEGLContextClientVersion != 2 && mEGLContextClientVersion != 3) { return configSpec; } /* We know none of the subclasses define EGL_RENDERABLE_TYPE. @@ -892,7 +892,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback int[] newConfigSpec = new int[len + 2]; System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1); newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE; - newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */ + if (mEGLContextClientVersion == 2) { + newConfigSpec[len] = EGL14.EGL_OPENGL_ES2_BIT; /* EGL_OPENGL_ES2_BIT */ + } else { + newConfigSpec[len] = EGLExt.EGL_OPENGL_ES3_BIT_KHR; /* EGL_OPENGL_ES3_BIT_KHR */ + } newConfigSpec[len+1] = EGL10.EGL_NONE; return newConfigSpec; } diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 48ef9dbe61e5..36c1d5c704d2 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -41,6 +41,9 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.StatFs; import android.provider.Settings; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStatVfs; import android.util.DisplayMetrics; import android.util.Slog; @@ -66,11 +69,8 @@ import javax.crypto.CipherInputStream; import javax.crypto.Mac; import javax.crypto.NoSuchPaddingException; -import libcore.io.ErrnoException; import libcore.io.IoUtils; -import libcore.io.Libcore; import libcore.io.Streams; -import libcore.io.StructStatVfs; /* * This service copies a downloaded apk to a file passed in as @@ -245,7 +245,7 @@ public class DefaultContainerService extends IntentService { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); try { - final StructStatVfs stat = Libcore.os.statvfs(path); + final StructStatVfs stat = Os.statvfs(path); final long totalSize = stat.f_blocks * stat.f_bsize; final long availSize = stat.f_bavail * stat.f_bsize; return new long[] { totalSize, availSize }; @@ -379,7 +379,7 @@ public class DefaultContainerService extends IntentService { } try { - Libcore.os.chmod(resFile.getAbsolutePath(), 0640); + Os.chmod(resFile.getAbsolutePath(), 0640); } catch (ErrnoException e) { Slog.e(TAG, "Could not chown APK: " + e.getMessage()); PackageHelper.destroySdDir(newCid); @@ -401,7 +401,7 @@ public class DefaultContainerService extends IntentService { } try { - Libcore.os.chmod(publicZipFile.getAbsolutePath(), 0644); + Os.chmod(publicZipFile.getAbsolutePath(), 0644); } catch (ErrnoException e) { Slog.e(TAG, "Could not chown public resource file: " + e.getMessage()); PackageHelper.destroySdDir(newCid); diff --git a/packages/InputDevices/res/raw/keyboard_layout_czech.kcm b/packages/InputDevices/res/raw/keyboard_layout_czech.kcm index f710a8ef3372..dc614db3f953 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_czech.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_czech.kcm @@ -13,7 +13,7 @@ # limitations under the License. # -# Czech keyboard layout. +# Czech (EU - qwerty) keyboard layout. # type OVERLAY @@ -26,6 +26,8 @@ key GRAVE { label: ';' base: ';' shift: '\u00b0' + ralt: '\u0060' + shift+ralt: '\u007e' } key 1 { @@ -38,6 +40,7 @@ key 1 { key 2 { label: '2' base: '\u011b' + capslock: '\u011a' shift: '2' ralt: '@' } @@ -45,6 +48,7 @@ key 2 { key 3 { label: '3' base: '\u0161' + capslock: '\u0160' shift: '3' ralt: '#' } @@ -52,6 +56,7 @@ key 3 { key 4 { label: '4' base: '\u010d' + capslock: '\u010c' shift: '4' ralt: '$' } @@ -59,6 +64,7 @@ key 4 { key 5 { label: '5' base: '\u0159' + capslock: '\u0158' shift: '5' ralt: '%' } @@ -66,6 +72,7 @@ key 5 { key 6 { label: '6' base: '\u017e' + capslock: '\u017d' shift: '6' ralt: '^' } @@ -73,6 +80,7 @@ key 6 { key 7 { label: '7' base: '\u00fd' + capslock: '\u00dd' shift: '7' ralt: '&' } @@ -80,6 +88,7 @@ key 7 { key 8 { label: '8' base: '\u00e1' + capslock: '\u00c1' shift: '8' ralt: '*' } @@ -87,6 +96,7 @@ key 8 { key 9 { label: '9' base: '\u00ed' + capslock: '\u00cd' shift: '9' ralt: '(' } @@ -94,6 +104,7 @@ key 9 { key 0 { label: '0' base: '\u00e9' + capslock: '\u00c9' shift: '0' ralt: ')' } @@ -180,6 +191,7 @@ key P { key LEFT_BRACKET { label: '\u00fa' base: '\u00fa' + capslock: '\u00da' shift: '/' ralt: '[' ralt+shift: '{' @@ -252,6 +264,7 @@ key L { key SEMICOLON { label: '\u016f' base: '\u016f' + capslock: '\u016e' shift: '"' ralt: ';' ralt+shift: ':' @@ -261,8 +274,8 @@ key APOSTROPHE { label: '\u00a7' base: '\u00a7' shift: '!' - ralt: '\'' - ralt+shift: '"' + ralt: '\u00a4' + ralt+shift: '\u005e' } key BACKSLASH { @@ -279,6 +292,8 @@ key PLUS { label: '\\' base: '\\' shift: '|' + ralt: '\u00df' + shift+ralt: '\u02dd' } key Z { @@ -330,6 +345,7 @@ key COMMA { base: ',' shift: '?' ralt: '<' + shift+ralt: '\u00d7' } key PERIOD { @@ -337,6 +353,7 @@ key PERIOD { base: '.' shift: ':' ralt: '>' + shift+ralt: '\u00f7' } key SLASH { diff --git a/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm b/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm index 0fabf02e5d2d..66c1c9878fc6 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm @@ -122,7 +122,7 @@ key Q { base: 'q' shift, capslock: 'Q' ralt: '\u00e4' - shift+ralt: '\u00c4' + shift+ralt, capslock+ralt: '\u00c4' } key W { @@ -130,7 +130,7 @@ key W { base: 'w' shift, capslock: 'W' ralt: '\u00e5' - shift+ralt: '\u00c5' + shift+ralt, capslock+ralt: '\u00c5' } key E { @@ -138,7 +138,7 @@ key E { base: 'e' shift, capslock: 'E' ralt: '\u00e9' - shift+ralt: '\u00c9' + shift+ralt, capslock+ralt: '\u00c9' } key R { @@ -153,7 +153,7 @@ key T { base: 't' shift, capslock: 'T' ralt: '\u00fe' - shift+ralt: '\u00de' + shift+ralt, capslock+ralt: '\u00de' } key Y { @@ -161,7 +161,7 @@ key Y { base: 'y' shift, capslock: 'Y' ralt: '\u00fc' - shift+ralt: '\u00dc' + shift+ralt, capslock+ralt: '\u00dc' } key U { @@ -169,7 +169,7 @@ key U { base: 'u' shift, capslock: 'U' ralt: '\u00fa' - shift+ralt: '\u00da' + shift+ralt, capslock+ralt: '\u00da' } key I { @@ -177,7 +177,7 @@ key I { base: 'i' shift, capslock: 'I' ralt: '\u00ed' - shift+ralt: '\u00cd' + shift+ralt, capslock+ralt: '\u00cd' } key O { @@ -185,7 +185,7 @@ key O { base: 'o' shift, capslock: 'O' ralt: '\u00f3' - shift+ralt: '\u00d3' + shift+ralt, capslock+ralt: '\u00d3' } key P { @@ -193,7 +193,7 @@ key P { base: 'p' shift, capslock: 'P' ralt: '\u00f6' - shift+ralt: '\u00d6' + shift+ralt, capslock+ralt: '\u00d6' } key LEFT_BRACKET { @@ -225,7 +225,7 @@ key A { base: 'a' shift, capslock: 'A' ralt: '\u00e1' - shift+ralt: '\u00c1' + shift+ralt, ralt+capslock: '\u00c1' } key S { @@ -241,7 +241,7 @@ key D { base: 'd' shift, capslock: 'D' ralt: '\u00f0' - shift+ralt: '\u00d0' + shift+ralt, capslock+ralt: '\u00d0' } key F { @@ -279,7 +279,7 @@ key L { base: 'l' shift, capslock: 'L' ralt: '\u00f8' - shift+ralt: '\u00d8' + shift+ralt, capslock+ralt: '\u00d8' } key SEMICOLON { @@ -313,7 +313,7 @@ key Z { base: 'z' shift, capslock: 'Z' ralt: '\u00e6' - shift+ralt: '\u00c6' + shift+ralt, capslock+ralt: '\u00c6' } key X { @@ -347,7 +347,7 @@ key N { base: 'n' shift, capslock: 'N' ralt: '\u00f1' - shift+ralt: '\u00d1' + shift+ralt, capslock+ralt: '\u00d1' } key M { @@ -362,7 +362,7 @@ key COMMA { base: ',' shift: '<' ralt: '\u00e7' - shift+ralt: '\u00c7' + shift+ralt, capslock+ralt: '\u00c7' } key PERIOD { diff --git a/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm b/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm index 70c1fa43ca48..2eb0f637b096 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm @@ -13,7 +13,7 @@ # limitations under the License. # -# Slovak keyboard layout. +# Slovak (EU - qwerty) keyboard layout. # type OVERLAY @@ -26,94 +26,90 @@ key GRAVE { label: ';' base: ';' shift: '\u00b0' - ralt: '`' - ralt+shift: '~' } key 1 { label: '1' base: '+' shift: '1' - ralt: '!' + ralt: '~' } key 2 { label: '2' base: '\u013e' shift: '2' - ralt: '@' + ralt: '\u02c7' } key 3 { label: '3' base: '\u0161' shift: '3' - ralt: '#' + ralt: '\u0302' } key 4 { label: '4' base: '\u010d' shift: '4' - ralt: '$' + ralt: '\u02d8' } key 5 { label: '5' base: '\u0165' shift: '5' - ralt: '%' + ralt: '\u00b0' } key 6 { label: '6' base: '\u017e' shift: '6' - ralt: '^' + ralt: '\u02db' } key 7 { label: '7' base: '\u00fd' shift: '7' - ralt: '&' + ralt: '\u0300' } key 8 { label: '8' base: '\u00e1' shift: '8' - ralt: '*' + ralt: '\u02d9' } key 9 { label: '9' base: '\u00ed' shift: '9' - ralt: '(' + ralt: '\u0301' } key 0 { label: '0' base: '\u00e9' shift: '0' - ralt: ')' + ralt: '\u02dd' } key MINUS { label: '=' base: '=' shift: '%' - ralt: '-' - ralt+shift: '_' + ralt: '\u0308' } key EQUALS { label: '\u00b4' base: '\u0301' shift: '\u030c' - ralt: '=' - ralt+shift: '+' + ralt: '\u00b8' } ### ROW 2 @@ -179,22 +175,21 @@ key P { label: 'P' base: 'p' shift, capslock: 'P' + ralt: '\'' } key LEFT_BRACKET { label: '\u00fa' base: '\u00fa' shift: '/' - ralt: '[' - ralt+shift: '{' + ralt: '\u00f7' } key RIGHT_BRACKET { label: '\u00e4' base: '\u00e4' shift: '(' - ralt: ']' - ralt+shift: '}' + ralt: '\u00d7' } ### ROW 3 @@ -209,24 +204,28 @@ key S { label: 'S' base: 's' shift, capslock: 'S' + ralt: '\u0111' } key D { label: 'D' base: 'd' shift, capslock: 'D' + ralt: '\u0110' } key F { label: 'F' base: 'f' shift, capslock: 'F' + ralt: '[' } key G { label: 'G' base: 'g' shift, capslock: 'G' + ralt: ']' } key H { @@ -245,64 +244,65 @@ key K { label: 'K' base: 'k' shift, capslock: 'K' + ralt: '\u0142' } key L { label: 'L' base: 'l' shift, capslock: 'L' + ralt: '\u0141' } key SEMICOLON { label: '\u00f4' base: '\u00f4' shift: '"' - ralt: ';' - ralt+shift: ':' + ralt: '$' } key APOSTROPHE { label: '\u00a7' base: '\u00a7' shift: '!' - ralt: '\'' - ralt+shift: '"' + ralt: '\u00df' } key BACKSLASH { label: '\u0148' base: '\u0148' shift: ')' - ralt: '\\' - ralt+shift: '|' + ralt: '\u00a4' } ### ROW 4 key PLUS { - label: '\\' - base: '\\' - shift: '|' - ralt: '&' - ralt+shift: '*' + label: '&' + base: '&' + shift: '*' + ralt: '<' } key Z { label: 'Z' base: 'z' shift, capslock: 'Z' + ralt: '>' } key X { label: 'X' base: 'x' shift, capslock: 'X' + ralt: '#' } key C { label: 'C' base: 'c' shift, capslock: 'C' + ralt: '&' } key V { @@ -316,12 +316,14 @@ key B { label: 'B' base: 'b' shift, capslock: 'B' + ralt: '{' } key N { label: 'N' base: 'n' shift, capslock: 'N' + ralt: '}' } key M { @@ -348,6 +350,5 @@ key SLASH { label: '-' base: '-' shift: '_' - ralt: '/' - ralt+shift: '?' + ralt: '*' } diff --git a/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm b/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm index a75d15487a63..9e204624b82d 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm @@ -56,12 +56,14 @@ key 4 { label: '4' base: '4' shift: '\u00e7' + ralt: '\u00b0' } key 5 { label: '5' base: '5' shift: '%' + ralt: '\u00a7' } key 6 { diff --git a/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm b/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm index ae93f4bc39b6..7fbd1a9b2828 100644 --- a/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm +++ b/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm @@ -56,12 +56,14 @@ key 4 { label: '4' base: '4' shift: '\u00e7' + ralt: '\u00b0' } key 5 { label: '5' base: '5' shift: '%' + ralt: '\u00a7' } key 6 { @@ -178,6 +180,8 @@ key LEFT_BRACKET { label: '\u00fc' base: '\u00fc' shift: '\u00e8' + capslock: '\u00dc' + capslock+shift: '\u00c8' ralt: '[' } @@ -248,12 +252,16 @@ key SEMICOLON { label: '\u00f6' base: '\u00f6' shift: '\u00e9' + capslock: '\u00d6' + capslock+shift: '\u00c9' } key APOSTROPHE { label: '\u00e4' base: '\u00e4' shift: '\u00e0' + capslock: '\u00c4' + capslock+shift: '\u00c0' ralt: '{' } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java index 751572c72761..bcb2e6d611a1 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java @@ -32,12 +32,11 @@ import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; import android.util.AttributeSet; +import android.util.MutableInt; import android.util.Slog; import android.view.View; import android.widget.TextView; -import libcore.util.MutableInt; - import java.lang.ref.WeakReference; import com.android.internal.widget.LockPatternUtils; diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index be7a9cdffbe9..f9cf5d278087 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -202,6 +202,7 @@ public class ImageWallpaper extends WallpaperService { if (mReceiver != null) { unregisterReceiver(mReceiver); } + mBackground = null; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 8957a7738064..194774dd981b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -168,6 +168,9 @@ public class PhoneStatusBarPolicy { if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { mSimState = IccCardConstants.State.ABSENT; } + else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) { + mSimState = IccCardConstants.State.CARD_IO_ERROR; + } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { mSimState = IccCardConstants.State.READY; } diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp index fe61918e1d86..18cd8eb7490d 100644 --- a/services/input/InputWindow.cpp +++ b/services/input/InputWindow.cpp @@ -36,6 +36,7 @@ bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const { bool InputWindowInfo::isTrustedOverlay() const { return layoutParamsType == TYPE_INPUT_METHOD || layoutParamsType == TYPE_INPUT_METHOD_DIALOG + || layoutParamsType == TYPE_MAGNIFICATION_OVERLAY || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY; } diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h index 28fa7ab42d44..bd325b5be27d 100644 --- a/services/input/InputWindow.h +++ b/services/input/InputWindow.h @@ -105,6 +105,7 @@ struct InputWindowInfo { TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19, TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20, TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21, + TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27, LAST_SYSTEM_WINDOW = 2999, }; diff --git a/services/java/com/android/server/am/NativeCrashListener.java b/services/java/com/android/server/am/NativeCrashListener.java index 2c7f1f13098b..493e1e47f52e 100644 --- a/services/java/com/android/server/am/NativeCrashListener.java +++ b/services/java/com/android/server/am/NativeCrashListener.java @@ -17,18 +17,18 @@ package com.android.server.am; import android.app.ApplicationErrorReport.CrashInfo; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructTimeval; +import android.system.StructUcred; import android.util.Slog; -import libcore.io.ErrnoException; -import libcore.io.Libcore; -import libcore.io.StructTimeval; -import libcore.io.StructUcred; - -import static libcore.io.OsConstants.*; +import static android.system.OsConstants.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; +import java.io.InterruptedIOException; import java.net.InetSocketAddress; import java.net.InetUnixAddress; @@ -76,7 +76,7 @@ final class NativeCrashListener extends Thread { try { CrashInfo ci = new CrashInfo(); ci.exceptionClassName = "Native crash"; - ci.exceptionMessage = Libcore.os.strsignal(mSignal); + ci.exceptionMessage = Os.strsignal(mSignal); ci.throwFileName = "unknown"; ci.throwClassName = "unknown"; ci.throwMethodName = "unknown"; @@ -116,22 +116,22 @@ final class NativeCrashListener extends Thread { } try { - FileDescriptor serverFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0); + FileDescriptor serverFd = Os.socket(AF_UNIX, SOCK_STREAM, 0); final InetUnixAddress sockAddr = new InetUnixAddress(DEBUGGERD_SOCKET_PATH); - Libcore.os.bind(serverFd, sockAddr, 0); - Libcore.os.listen(serverFd, 1); + Os.bind(serverFd, sockAddr, 0); + Os.listen(serverFd, 1); while (true) { InetSocketAddress peer = new InetSocketAddress(); FileDescriptor peerFd = null; try { if (MORE_DEBUG) Slog.v(TAG, "Waiting for debuggerd connection"); - peerFd = Libcore.os.accept(serverFd, peer); + peerFd = Os.accept(serverFd, peer); if (MORE_DEBUG) Slog.v(TAG, "Got debuggerd socket " + peerFd); if (peerFd != null) { // Only the superuser is allowed to talk to us over this socket StructUcred credentials = - Libcore.os.getsockoptUcred(peerFd, SOL_SOCKET, SO_PEERCRED); + Os.getsockoptUcred(peerFd, SOL_SOCKET, SO_PEERCRED); if (credentials.uid == 0) { // the reporting thread may take responsibility for // acking the debugger; make sure we play along. @@ -145,7 +145,7 @@ final class NativeCrashListener extends Thread { // byte written is irrelevant. if (peerFd != null) { try { - Libcore.os.write(peerFd, ackSignal, 0, 1); + Os.write(peerFd, ackSignal, 0, 1); } catch (Exception e) { /* we don't care about failures here */ if (MORE_DEBUG) { @@ -153,7 +153,7 @@ final class NativeCrashListener extends Thread { } } try { - Libcore.os.close(peerFd); + Os.close(peerFd); } catch (ErrnoException e) { if (MORE_DEBUG) { Slog.d(TAG, "Exception closing socket: " + e.getMessage()); @@ -178,10 +178,10 @@ final class NativeCrashListener extends Thread { } static int readExactly(FileDescriptor fd, byte[] buffer, int offset, int numBytes) - throws ErrnoException { + throws ErrnoException, InterruptedIOException { int totalRead = 0; while (numBytes > 0) { - int n = Libcore.os.read(fd, buffer, offset + totalRead, numBytes); + int n = Os.read(fd, buffer, offset + totalRead, numBytes); if (n <= 0) { if (DEBUG) { Slog.w(TAG, "Needed " + numBytes + " but saw " + n); @@ -202,8 +202,8 @@ final class NativeCrashListener extends Thread { try { StructTimeval timeout = StructTimeval.fromMillis(SOCKET_TIMEOUT_MILLIS); - Libcore.os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, timeout); - Libcore.os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, timeout); + Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, timeout); + Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, timeout); // first, the pid and signal number int headerBytes = readExactly(fd, buf, 0, 8); @@ -237,7 +237,7 @@ final class NativeCrashListener extends Thread { int bytes; do { // get some data - bytes = Libcore.os.read(fd, buf, 0, buf.length); + bytes = Os.read(fd, buf, 0, buf.length); if (bytes > 0) { if (MORE_DEBUG) { String s = new String(buf, 0, bytes, "UTF-8"); diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java index 09cb344531c3..5305c8f2e945 100644 --- a/services/java/com/android/server/am/UsageStatsService.java +++ b/services/java/com/android/server/am/UsageStatsService.java @@ -75,42 +75,44 @@ public final class UsageStatsService extends IUsageStats.Stub { private static final boolean localLOGV = false; private static final boolean REPORT_UNEXPECTED = false; private static final String TAG = "UsageStats"; - + // Current on-disk Parcel version private static final int VERSION = 1008; private static final int CHECKIN_VERSION = 4; - + private static final String FILE_PREFIX = "usage-"; private static final String FILE_HISTORY = FILE_PREFIX + "history.xml"; - private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms - + private static final int FILE_WRITE_INTERVAL = (localLOGV) ? 0 : 30*60*1000; // 30m in ms + private static final int MAX_NUM_FILES = 5; - + private static final int NUM_LAUNCH_TIME_BINS = 10; private static final int[] LAUNCH_TIME_BINS = { 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000 }; - + static IUsageStats sService; private Context mContext; // structure used to maintain statistics since the last checkin. - final private ArrayMap<String, PkgUsageStatsExtended> mStats; + final private ArrayMap<String, PkgUsageStatsExtended> mStats + = new ArrayMap<String, PkgUsageStatsExtended>(); // Maintains the last time any component was resumed, for all time. - final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes; + final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes + = new ArrayMap<String, ArrayMap<String, Long>>(); // To remove last-resume time stats when a pacakge is removed. private PackageMonitor mPackageMonitor; // Lock to update package stats. Methods suffixed by SLOCK should invoked with // this lock held - final Object mStatsLock; + final Object mStatsLock = new Object(); // Lock to write to file. Methods suffixed by FLOCK should invoked with // this lock held. - final Object mFileLock; + final Object mFileLock = new Object(); // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks private String mLastResumedPkg; private String mLastResumedComp; @@ -120,52 +122,53 @@ public final class UsageStatsService extends IUsageStats.Stub { private String mFileLeaf; private File mDir; - private Calendar mCal; // guarded by itself + private final Calendar mCal // guarded by itself + = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); private final AtomicInteger mLastWriteDay = new AtomicInteger(-1); private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0); private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false); - + static class TimeStats { - int count; - int[] times = new int[NUM_LAUNCH_TIME_BINS]; - + int mCount; + final int[] mTimes = new int[NUM_LAUNCH_TIME_BINS]; + TimeStats() { } - + void incCount() { - count++; + mCount++; } - + void add(int val) { final int[] bins = LAUNCH_TIME_BINS; for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) { if (val < bins[i]) { - times[i]++; + mTimes[i]++; return; } } - times[NUM_LAUNCH_TIME_BINS-1]++; + mTimes[NUM_LAUNCH_TIME_BINS-1]++; } - + TimeStats(Parcel in) { - count = in.readInt(); - final int[] localTimes = times; + mCount = in.readInt(); + final int[] localTimes = mTimes; for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { localTimes[i] = in.readInt(); } } - + void writeToParcel(Parcel out) { - out.writeInt(count); - final int[] localTimes = times; + out.writeInt(mCount); + final int[] localTimes = mTimes; for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { out.writeInt(localTimes[i]); } } } - - private class PkgUsageStatsExtended { + + static class PkgUsageStatsExtended { final ArrayMap<String, TimeStats> mLaunchTimes = new ArrayMap<String, TimeStats>(); final ArrayMap<String, TimeStats> mFullyDrawnTimes @@ -174,18 +177,18 @@ public final class UsageStatsService extends IUsageStats.Stub { long mUsageTime; long mPausedTime; long mResumedTime; - + PkgUsageStatsExtended() { mLaunchCount = 0; mUsageTime = 0; } - + PkgUsageStatsExtended(Parcel in) { mLaunchCount = in.readInt(); mUsageTime = in.readLong(); if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount + ", Usage time:" + mUsageTime); - + final int numLaunchTimeStats = in.readInt(); if (localLOGV) Slog.v(TAG, "Reading launch times: " + numLaunchTimeStats); mLaunchTimes.ensureCapacity(numLaunchTimeStats); @@ -209,16 +212,16 @@ public final class UsageStatsService extends IUsageStats.Stub { void updateResume(String comp, boolean launched) { if (launched) { - mLaunchCount ++; + mLaunchCount++; } mResumedTime = SystemClock.elapsedRealtime(); } - + void updatePause() { mPausedTime = SystemClock.elapsedRealtime(); mUsageTime += (mPausedTime - mResumedTime); } - + void addLaunchCount(String comp) { TimeStats times = mLaunchTimes.get(comp); if (times == null) { @@ -227,7 +230,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } times.incCount(); } - + void addLaunchTime(String comp, int millis) { TimeStats times = mLaunchTimes.get(comp); if (times == null) { @@ -262,7 +265,7 @@ public final class UsageStatsService extends IUsageStats.Stub { mFullyDrawnTimes.valueAt(i).writeToParcel(out); } } - + void clear() { mLaunchTimes.clear(); mFullyDrawnTimes.clear(); @@ -270,32 +273,25 @@ public final class UsageStatsService extends IUsageStats.Stub { mUsageTime = 0; } } - + UsageStatsService(String dir) { - mStats = new ArrayMap<String, PkgUsageStatsExtended>(); - mLastResumeTimes = new ArrayMap<String, ArrayMap<String, Long>>(); - mStatsLock = new Object(); - mFileLock = new Object(); + if (localLOGV) Slog.v(TAG, "UsageStatsService: " + dir); mDir = new File(dir); - mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0")); - mDir.mkdir(); - - // Remove any old usage files from previous versions. + + // Remove any old /data/system/usagestats.* files from previous versions. File parentDir = mDir.getParentFile(); - String fList[] = parentDir.list(); - if (fList != null) { + String files[] = parentDir.list(); + if (files != null) { String prefix = mDir.getName() + "."; - int i = fList.length; - while (i > 0) { - i--; - if (fList[i].startsWith(prefix)) { - Slog.i(TAG, "Deleting old usage file: " + fList[i]); - (new File(parentDir, fList[i])).delete(); + for (String file : files) { + if (file.startsWith(prefix)) { + Slog.i(TAG, "Deleting old usage file: " + file); + (new File(parentDir, file)).delete(); } } } - + // Update current stats which are binned by date mFileLeaf = getCurrentDateStr(FILE_PREFIX); mFile = new File(mDir, mFileLeaf); @@ -312,11 +308,11 @@ public final class UsageStatsService extends IUsageStats.Stub { */ private String getCurrentDateStr(String prefix) { StringBuilder sb = new StringBuilder(); + if (prefix != null) { + sb.append(prefix); + } synchronized (mCal) { mCal.setTimeInMillis(System.currentTimeMillis()); - if (prefix != null) { - sb.append(prefix); - } sb.append(mCal.get(Calendar.YEAR)); int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1; if (mm < 10) { @@ -331,17 +327,20 @@ public final class UsageStatsService extends IUsageStats.Stub { } return sb.toString(); } - + private Parcel getParcelForFile(File file) throws IOException { FileInputStream stream = new FileInputStream(file); - byte[] raw = readFully(stream); - Parcel in = Parcel.obtain(); - in.unmarshall(raw, 0, raw.length); - in.setDataPosition(0); - stream.close(); - return in; + try { + byte[] raw = readFully(stream); + Parcel in = Parcel.obtain(); + in.unmarshall(raw, 0, raw.length); + in.setDataPosition(0); + return in; + } finally { + stream.close(); + } } - + private void readStatsFromFile() { File newFile = mFile; synchronized (mFileLock) { @@ -358,12 +357,13 @@ public final class UsageStatsService extends IUsageStats.Stub { } } } - + private void readStatsFLOCK(File file) throws IOException { Parcel in = getParcelForFile(file); int vers = in.readInt(); - if (vers != VERSION) { - Slog.w(TAG, "Usage stats version changed; dropping"); + if (vers != VERSION) { // vers will be 0 if the parcel file was empty + Slog.w(TAG, "Usage stats version of " + file + " changed from " + vers + " to " + + VERSION + "; dropping"); return; } int N = in.readInt(); @@ -384,12 +384,12 @@ public final class UsageStatsService extends IUsageStats.Stub { private void readHistoryStatsFromFile() { synchronized (mFileLock) { if (mHistoryFile.getBaseFile().exists()) { - readHistoryStatsFLOCK(mHistoryFile); + readHistoryStatsFLOCK(); } } } - private void readHistoryStatsFLOCK(AtomicFile file) { + private void readHistoryStatsFLOCK() { FileInputStream fis = null; try { fis = mHistoryFile.openRead(); @@ -472,12 +472,12 @@ public final class UsageStatsService extends IUsageStats.Stub { } return fileList; } - + private void checkFileLimitFLOCK() { // Get all usage stats output files ArrayList<String> fileList = getUsageStatsFileListFLOCK(); if (fileList == null) { - // Strange but we dont have to delete any thing + // Empty /data/system/usagestats/ so we don't have anything to delete return; } int count = fileList.size(); @@ -577,8 +577,8 @@ public final class UsageStatsService extends IUsageStats.Stub { } if (dayChanged || forceWriteHistoryStats) { - // Write history stats daily, or when forced (due to shutdown). - writeHistoryStatsFLOCK(mHistoryFile); + // Write history stats daily or when forced (due to shutdown) or when debugging. + writeHistoryStatsFLOCK(); } // Delete the backup file @@ -640,10 +640,10 @@ public final class UsageStatsService extends IUsageStats.Stub { } } - private void writeHistoryStatsFLOCK(AtomicFile historyFile) { + private void writeHistoryStatsFLOCK() { FileOutputStream fos = null; try { - fos = historyFile.startWrite(); + fos = mHistoryFile.startWrite(); XmlSerializer out = new FastXmlSerializer(); out.setOutput(fos, "utf-8"); out.startDocument(null, true); @@ -666,11 +666,11 @@ public final class UsageStatsService extends IUsageStats.Stub { out.endTag(null, "usage-history"); out.endDocument(); - historyFile.finishWrite(fos); + mHistoryFile.finishWrite(fos); } catch (IOException e) { Slog.w(TAG,"Error writing history stats" + e); if (fos != null) { - historyFile.failWrite(fos); + mHistoryFile.failWrite(fos); } } } @@ -713,7 +713,8 @@ public final class UsageStatsService extends IUsageStats.Stub { sService = asInterface(b); return sService; } - + + @Override public void noteResumeComponent(ComponentName componentName) { enforceCallingPermission(); String pkgName; @@ -722,7 +723,7 @@ public final class UsageStatsService extends IUsageStats.Stub { ((pkgName = componentName.getPackageName()) == null)) { return; } - + final boolean samePackage = pkgName.equals(mLastResumedPkg); if (mIsResumed) { if (mLastResumedPkg != null) { @@ -736,14 +737,14 @@ public final class UsageStatsService extends IUsageStats.Stub { } } } - + final boolean sameComp = samePackage && componentName.getClassName().equals(mLastResumedComp); - + mIsResumed = true; mLastResumedPkg = pkgName; mLastResumedComp = componentName.getClassName(); - + if (localLOGV) Slog.i(TAG, "started component:" + pkgName); PkgUsageStatsExtended pus = mStats.get(pkgName); if (pus == null) { @@ -764,9 +765,10 @@ public final class UsageStatsService extends IUsageStats.Stub { } } + @Override public void notePauseComponent(ComponentName componentName) { enforceCallingPermission(); - + synchronized (mStatsLock) { String pkgName; if ((componentName == null) || @@ -779,9 +781,9 @@ public final class UsageStatsService extends IUsageStats.Stub { return; } mIsResumed = false; - + if (localLOGV) Slog.i(TAG, "paused component:"+pkgName); - + PkgUsageStatsExtended pus = mStats.get(pkgName); if (pus == null) { // Weird some error here @@ -790,11 +792,12 @@ public final class UsageStatsService extends IUsageStats.Stub { } pus.updatePause(); } - + // Persist current data to file if needed. writeStatsToFile(false, false); } - + + @Override public void noteLaunchTime(ComponentName componentName, int millis) { enforceCallingPermission(); String pkgName; @@ -802,10 +805,10 @@ public final class UsageStatsService extends IUsageStats.Stub { ((pkgName = componentName.getPackageName()) == null)) { return; } - + // Persist current data to file if needed. writeStatsToFile(false, false); - + synchronized (mStatsLock) { PkgUsageStatsExtended pus = mStats.get(pkgName); if (pus != null) { @@ -813,7 +816,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } } } - + public void noteFullyDrawnTime(ComponentName componentName, int millis) { enforceCallingPermission(); String pkgName; @@ -840,7 +843,8 @@ public final class UsageStatsService extends IUsageStats.Stub { mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, Binder.getCallingPid(), Binder.getCallingUid(), null); } - + + @Override public PkgUsageStats getPkgUsageStats(ComponentName componentName) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.PACKAGE_USAGE_STATS, null); @@ -860,7 +864,8 @@ public final class UsageStatsService extends IUsageStats.Stub { return new PkgUsageStats(pkgName, launchCount, usageTime, lastResumeTimes); } } - + + @Override public PkgUsageStats[] getAllPkgUsageStats() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.PACKAGE_USAGE_STATS, null); @@ -886,8 +891,8 @@ public final class UsageStatsService extends IUsageStats.Stub { return retArr; } } - - static byte[] readFully(FileInputStream stream) throws java.io.IOException { + + static byte[] readFully(FileInputStream stream) throws IOException { int pos = 0; int avail = stream.available(); byte[] data = new byte[avail]; @@ -905,7 +910,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } } } - + private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput, boolean deleteAfterPrint, HashSet<String> packages) { List<String> fileList = getUsageStatsFileListFLOCK(); @@ -934,15 +939,12 @@ public final class UsageStatsService extends IUsageStats.Stub { // Delete old file after collecting info only for checkin requests dFile.delete(); } - } catch (FileNotFoundException e) { - Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file); - return; } catch (IOException e) { Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file); - } + } } } - + private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw, String date, boolean isCompactOutput, HashSet<String> packages) { StringBuilder sb = new StringBuilder(512); @@ -953,19 +955,19 @@ public final class UsageStatsService extends IUsageStats.Stub { } else { sb.append("Date: "); } - + sb.append(date); - + int vers = in.readInt(); if (vers != VERSION) { sb.append(" (old data version)"); pw.println(sb.toString()); return; } - + pw.println(sb.toString()); int N = in.readInt(); - + while (N > 0) { N--; String pkgName = in.readString(); @@ -992,10 +994,10 @@ public final class UsageStatsService extends IUsageStats.Stub { sb.append(activity); TimeStats times = pus.mLaunchTimes.valueAt(i); sb.append(','); - sb.append(times.count); + sb.append(times.mCount); for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) { sb.append(","); - sb.append(times.times[j]); + sb.append(times.mTimes[j]); } sb.append('\n'); } @@ -1007,7 +1009,7 @@ public final class UsageStatsService extends IUsageStats.Stub { TimeStats times = pus.mFullyDrawnTimes.valueAt(i); for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) { sb.append(","); - sb.append(times.times[j]); + sb.append(times.mTimes[j]); } sb.append('\n'); } @@ -1027,26 +1029,26 @@ public final class UsageStatsService extends IUsageStats.Stub { sb.append(pus.mLaunchTimes.keyAt(i)); TimeStats times = pus.mLaunchTimes.valueAt(i); sb.append(": "); - sb.append(times.count); + sb.append(times.mCount); sb.append(" starts"); int lastBin = 0; for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) { - if (times.times[j] != 0) { + if (times.mTimes[j] != 0) { sb.append(", "); sb.append(lastBin); sb.append('-'); sb.append(LAUNCH_TIME_BINS[j]); sb.append("ms="); - sb.append(times.times[j]); + sb.append(times.mTimes[j]); } lastBin = LAUNCH_TIME_BINS[j]; } - if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) { + if (times.mTimes[NUM_LAUNCH_TIME_BINS-1] != 0) { sb.append(", "); sb.append(">="); sb.append(lastBin); sb.append("ms="); - sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); + sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]); } sb.append('\n'); } @@ -1059,7 +1061,7 @@ public final class UsageStatsService extends IUsageStats.Stub { boolean needComma = false; int lastBin = 0; for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) { - if (times.times[j] != 0) { + if (times.mTimes[j] != 0) { if (needComma) { sb.append(", "); } else { @@ -1069,27 +1071,27 @@ public final class UsageStatsService extends IUsageStats.Stub { sb.append('-'); sb.append(LAUNCH_TIME_BINS[j]); sb.append("ms="); - sb.append(times.times[j]); + sb.append(times.mTimes[j]); } lastBin = LAUNCH_TIME_BINS[j]; } - if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) { + if (times.mTimes[NUM_LAUNCH_TIME_BINS-1] != 0) { if (needComma) { sb.append(", "); } sb.append(">="); sb.append(lastBin); sb.append("ms="); - sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); + sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]); } sb.append('\n'); } } - + pw.write(sb.toString()); } } - + /** * Searches array of arguments for the specified string * @param args array of argument strings @@ -1106,7 +1108,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } return false; } - + /** * Searches array of arguments for the specified string's data * @param args array of argument strings @@ -1125,11 +1127,11 @@ public final class UsageStatsService extends IUsageStats.Stub { } return null; } - - @Override + /* - * The data persisted to file is parsed and the stats are computed. + * The data persisted to file is parsed and the stats are computed. */ + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { @@ -1143,23 +1145,23 @@ public final class UsageStatsService extends IUsageStats.Stub { final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c"); final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d"); final String rawPackages = scanArgsData(args, "--packages"); - + // Make sure the current stats are written to the file. This // doesn't need to be done if we are deleting files after printing, - // since it that case we won't print the current stats. + // since in that case we won't print the current stats. if (!deleteAfterPrint) { writeStatsToFile(true, false); } - + HashSet<String> packages = null; if (rawPackages != null) { if (!"*".equals(rawPackages)) { // A * is a wildcard to show all packages. String[] names = rawPackages.split(","); + if (names.length != 0) { + packages = new HashSet<String>(); + } for (String n : names) { - if (packages == null) { - packages = new HashSet<String>(); - } packages.add(n); } } @@ -1169,7 +1171,7 @@ public final class UsageStatsService extends IUsageStats.Stub { Slog.w(TAG, "Checkin without packages"); return; } - + synchronized (mFileLock) { collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages); } diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java index 8cd9d935db18..b776ce14b018 100644 --- a/services/java/com/android/server/pm/Installer.java +++ b/services/java/com/android/server/pm/Installer.java @@ -201,7 +201,7 @@ public final class Installer { return execute(builder.toString()); } - public int dexopt(String apkPath, int uid, boolean isPublic) { + public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) { StringBuilder builder = new StringBuilder("dexopt"); builder.append(' '); builder.append(apkPath); @@ -209,10 +209,13 @@ public final class Installer { builder.append(uid); builder.append(isPublic ? " 1" : " 0"); builder.append(" *"); // No pkgName arg present + builder.append(' '); + builder.append(instructionSet); return execute(builder.toString()); } - public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName) { + public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName, + String instructionSet) { StringBuilder builder = new StringBuilder("dexopt"); builder.append(' '); builder.append(apkPath); @@ -221,6 +224,8 @@ public final class Installer { builder.append(isPublic ? " 1" : " 0"); builder.append(' '); builder.append(pkgName); + builder.append(' '); + builder.append(instructionSet); return execute(builder.toString()); } @@ -235,19 +240,23 @@ public final class Installer { return execute(builder.toString()); } - public int movedex(String srcPath, String dstPath) { + public int movedex(String srcPath, String dstPath, String instructionSet) { StringBuilder builder = new StringBuilder("movedex"); builder.append(' '); builder.append(srcPath); builder.append(' '); builder.append(dstPath); + builder.append(' '); + builder.append(instructionSet); return execute(builder.toString()); } - public int rmdex(String codePath) { + public int rmdex(String codePath, String instructionSet) { StringBuilder builder = new StringBuilder("rmdex"); builder.append(' '); builder.append(codePath); + builder.append(' '); + builder.append(instructionSet); return execute(builder.toString()); } @@ -334,7 +343,7 @@ public final class Installer { } public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath, - String fwdLockApkPath, String asecPath, PackageStats pStats) { + String fwdLockApkPath, String asecPath, String instructionSet, PackageStats pStats) { StringBuilder builder = new StringBuilder("getsize"); builder.append(' '); builder.append(pkgName); @@ -348,6 +357,8 @@ public final class Installer { builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!"); builder.append(' '); builder.append(asecPath != null ? asecPath : "!"); + builder.append(' '); + builder.append(instructionSet); String s = transaction(builder.toString()); String res[] = s.split(" "); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index f881415c280a..d5b84e9b3a32 100755 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -23,14 +23,15 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; +import static android.system.OsConstants.S_IRWXU; +import static android.system.OsConstants.S_IRGRP; +import static android.system.OsConstants.S_IXGRP; +import static android.system.OsConstants.S_IROTH; +import static android.system.OsConstants.S_IXOTH; import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.ArrayUtils.removeInt; -import static libcore.io.OsConstants.S_IRWXU; -import static libcore.io.OsConstants.S_IRGRP; -import static libcore.io.OsConstants.S_IXGRP; -import static libcore.io.OsConstants.S_IROTH; -import static libcore.io.OsConstants.S_IXOTH; +import android.content.pm.PackageParser.*; import com.android.internal.app.IMediaContainerService; import com.android.internal.app.ResolverActivity; import com.android.internal.content.NativeLibraryHelper; @@ -78,7 +79,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; import android.content.pm.PackageParser; -import android.content.pm.PackageParser.ActivityIntentInfo; import android.content.pm.PackageStats; import android.content.pm.PackageUserState; import android.content.pm.ParceledListSlice; @@ -117,6 +117,9 @@ import android.os.UserHandle; import android.os.UserManager; import android.security.KeyStore; import android.security.SystemKeyStore; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.EventLog; @@ -156,10 +159,8 @@ import java.util.List; import java.util.Map; import java.util.Set; -import libcore.io.ErrnoException; +import dalvik.system.VMRuntime; import libcore.io.IoUtils; -import libcore.io.Libcore; -import libcore.io.StructStat; import com.android.internal.R; @@ -257,11 +258,14 @@ public class PackageManagerService extends IPackageManager.Stub { private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; private static final String LIB_DIR_NAME = "lib"; + private static final String LIB64_DIR_NAME = "lib64"; private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay"; static final String mTempContainerPrefix = "smdl2tmp"; + private static String sPreferredInstructionSet; + private static final String IDMAP_PREFIX = "/data/resource-cache/"; private static final String IDMAP_SUFFIX = "@idmap"; @@ -1201,27 +1205,38 @@ public class PackageManagerService extends IPackageManager.Stub { boolean didDexOpt = false; + final List<String> instructionSets = getAllInstructionSets(); + /** * Ensure all external libraries have had dexopt run on them. */ if (mSharedLibraries.size() > 0) { - Iterator<SharedLibraryEntry> libs = mSharedLibraries.values().iterator(); - while (libs.hasNext()) { - String lib = libs.next().path; - if (lib == null) { - continue; - } - try { - if (dalvik.system.DexFile.isDexOptNeededInternal(lib, null, false)) { - alreadyDexOpted.add(lib); - mInstaller.dexopt(lib, Process.SYSTEM_UID, true); - didDexOpt = true; + // NOTE: For now, we're compiling these system "shared libraries" + // (and framework jars) into all available architectures. It's possible + // to compile them only when we come across an app that uses them (there's + // already logic for that in scanPackageLI) but that adds some complexity. + for (String instructionSet : instructionSets) { + for (SharedLibraryEntry libEntry : mSharedLibraries.values()) { + final String lib = libEntry.path; + if (lib == null) { + continue; + } + + try { + if (dalvik.system.DexFile.isDexOptNeededInternal( + lib, null, instructionSet, false)) { + alreadyDexOpted.add(lib); + + // The list of "shared libraries" we have at this point is + mInstaller.dexopt(lib, Process.SYSTEM_UID, true, instructionSet); + didDexOpt = true; + } + } catch (FileNotFoundException e) { + Slog.w(TAG, "Library not found: " + lib); + } catch (IOException e) { + Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? " + + e.getMessage()); } - } catch (FileNotFoundException e) { - Slog.w(TAG, "Library not found: " + lib); - } catch (IOException e) { - Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? " - + e.getMessage()); } } } @@ -1244,49 +1259,37 @@ public class PackageManagerService extends IPackageManager.Stub { */ String[] frameworkFiles = frameworkDir.list(); if (frameworkFiles != null) { - for (int i=0; i<frameworkFiles.length; i++) { - File libPath = new File(frameworkDir, frameworkFiles[i]); - String path = libPath.getPath(); - // Skip the file if we alrady did it. - if (alreadyDexOpted.contains(path)) { - continue; - } - // Skip the file if it is not a type we want to dexopt. - if (!path.endsWith(".apk") && !path.endsWith(".jar")) { - continue; - } - try { - if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, false)) { - mInstaller.dexopt(path, Process.SYSTEM_UID, true); - didDexOpt = true; + // TODO: We could compile these only for the most preferred ABI. We should + // first double check that the dex files for these commands are not referenced + // by other system apps. + for (String instructionSet : instructionSets) { + for (int i=0; i<frameworkFiles.length; i++) { + File libPath = new File(frameworkDir, frameworkFiles[i]); + String path = libPath.getPath(); + // Skip the file if we already did it. + if (alreadyDexOpted.contains(path)) { + continue; + } + // Skip the file if it is not a type we want to dexopt. + if (!path.endsWith(".apk") && !path.endsWith(".jar")) { + continue; + } + try { + if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, instructionSet, false)) { + mInstaller.dexopt(path, Process.SYSTEM_UID, true, instructionSet); + didDexOpt = true; + } + } catch (FileNotFoundException e) { + Slog.w(TAG, "Jar not found: " + path); + } catch (IOException e) { + Slog.w(TAG, "Exception reading jar: " + path, e); } - } catch (FileNotFoundException e) { - Slog.w(TAG, "Jar not found: " + path); - } catch (IOException e) { - Slog.w(TAG, "Exception reading jar: " + path, e); } } } if (didDexOpt) { - File dalvikCacheDir = new File(dataDir, "dalvik-cache"); - - // If we had to do a dexopt of one of the previous - // things, then something on the system has changed. - // Consider this significant, and wipe away all other - // existing dexopt files to ensure we don't leave any - // dangling around. - String[] files = dalvikCacheDir.list(); - if (files != null) { - for (int i=0; i<files.length; i++) { - String fn = files[i]; - if (fn.startsWith("data@app@") - || fn.startsWith("data@app-private@")) { - Slog.i(TAG, "Pruning dalvik file: " + fn); - (new File(dalvikCacheDir, fn)).delete(); - } - } - } + pruneDexFiles(new File(dataDir, "dalvik-cache")); } // Collect vendor overlay packages. @@ -1456,6 +1459,12 @@ public class PackageManagerService extends IPackageManager.Stub { // the correct library paths. updateAllSharedLibrariesLPw(); + + for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) { + adjustCpuAbisForSharedUserLPw(setting.packages, true /* do dexopt */, + false /* force dexopt */, false /* defer dexopt */); + } + EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis()); Slog.i(TAG, "Time to scan packages: " @@ -1502,6 +1511,37 @@ public class PackageManagerService extends IPackageManager.Stub { } // synchronized (mInstallLock) } + private static void pruneDexFiles(File cacheDir) { + // If we had to do a dexopt of one of the previous + // things, then something on the system has changed. + // Consider this significant, and wipe away all other + // existing dexopt files to ensure we don't leave any + // dangling around. + // + // Additionally, delete all dex files from the root directory + // since there shouldn't be any there anyway. + File[] files = cacheDir.listFiles(); + if (files != null) { + for (File file : files) { + if (!file.isDirectory()) { + Slog.i(TAG, "Pruning dalvik file: " + file.getAbsolutePath()); + file.delete(); + } else { + File[] subDirList = file.listFiles(); + if (subDirList != null) { + for (File subDirFile : subDirList) { + final String fn = subDirFile.getName(); + if (fn.startsWith("data@app@") || fn.startsWith("data@app-private@")) { + Slog.i(TAG, "Pruning dalvik file: " + fn); + subDirFile.delete(); + } + } + } + } + } + } + } + public boolean isFirstBoot() { return !mRestoredSettings; } @@ -1792,7 +1832,6 @@ public class PackageManagerService extends IPackageManager.Stub { PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - PackageInfo pi; final PackageSetting ps = (PackageSetting) p.mExtras; if (ps == null) { return null; @@ -3726,7 +3765,8 @@ public class PackageManagerService extends IPackageManager.Stub { + " better than installed " + ps.versionCode); InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps), - ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); + ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString, + getAppInstructionSetFromSettings(ps)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } @@ -3790,7 +3830,8 @@ public class PackageManagerService extends IPackageManager.Stub { + ps.codePathString + ": new version " + pkg.mVersionCode + " better than installed " + ps.versionCode); InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps), - ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); + ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString, + getAppInstructionSetFromSettings(ps)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } @@ -3824,8 +3865,6 @@ public class PackageManagerService extends IPackageManager.Stub { codePath = pkg.mScanPath; // Set application objects path explicitly. setApplicationInfoPaths(pkg, codePath, resPath); - // Applications can run with the primary Cpu Abi unless otherwise is specified - pkg.applicationInfo.requiredCpuAbi = null; // Note that we invoke the following method only if we are about to unpack an application PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime, user); @@ -3905,12 +3944,16 @@ public class PackageManagerService extends IPackageManager.Stub { } } + @Override public void performBootDexOpt() { - HashSet<PackageParser.Package> pkgs = null; + enforceSystemOrRoot("Only the system can request dexopt be performed"); + + final HashSet<PackageParser.Package> pkgs; synchronized (mPackages) { pkgs = mDeferredDexOpt; mDeferredDexOpt = null; } + if (pkgs != null) { int i = 0; for (PackageParser.Package pkg : pkgs) { @@ -3927,16 +3970,17 @@ public class PackageManagerService extends IPackageManager.Stub { PackageParser.Package p = pkg; synchronized (mInstallLock) { if (!p.mDidDexOpt) { - performDexOptLI(p, false, false, true); + performDexOptLI(p, false /* force dex */, false /* defer */, + true /* include dependencies */); } } } } } + @Override public boolean performDexOpt(String packageName) { enforceSystemOrRoot("Only the system can request dexopt be performed"); - if (!mNoDexOpt) { return false; } @@ -3949,12 +3993,13 @@ public class PackageManagerService extends IPackageManager.Stub { } } synchronized (mInstallLock) { - return performDexOptLI(p, false, false, true) == DEX_OPT_PERFORMED; + return performDexOptLI(p, false /* force dex */, false /* defer */, + true /* include dependencies */) == DEX_OPT_PERFORMED; } } - private void performDexOptLibsLI(ArrayList<String> libs, boolean forceDex, boolean defer, - HashSet<String> done) { + private void performDexOptLibsLI(ArrayList<String> libs, String instructionSet, boolean forceDex, + boolean defer, HashSet<String> done) { for (int i=0; i<libs.size(); i++) { PackageParser.Package libPkg; String libName; @@ -3968,7 +4013,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } if (libPkg != null && !done.contains(libName)) { - performDexOptLI(libPkg, forceDex, defer, done); + performDexOptLI(libPkg, instructionSet, forceDex, defer, done); } } } @@ -3978,24 +4023,29 @@ public class PackageManagerService extends IPackageManager.Stub { static final int DEX_OPT_DEFERRED = 2; static final int DEX_OPT_FAILED = -1; - private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer, - HashSet<String> done) { - boolean performed = false; + private int performDexOptLI(PackageParser.Package pkg, String instructionSetOverride, + boolean forceDex, + boolean defer, HashSet<String> done) { + final String instructionSet = instructionSetOverride != null ? + instructionSetOverride : getAppInstructionSet(pkg.applicationInfo); + if (done != null) { done.add(pkg.packageName); if (pkg.usesLibraries != null) { - performDexOptLibsLI(pkg.usesLibraries, forceDex, defer, done); + performDexOptLibsLI(pkg.usesLibraries, instructionSet, forceDex, defer, done); } if (pkg.usesOptionalLibraries != null) { - performDexOptLibsLI(pkg.usesOptionalLibraries, forceDex, defer, done); + performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSet, forceDex, defer, done); } } + + boolean performed = false; if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) { String path = pkg.mScanPath; int ret = 0; try { - if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path, pkg.packageName, - defer)) { + if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path, + pkg.packageName, instructionSet, defer)) { if (!forceDex && defer) { if (mDeferredDexOpt == null) { mDeferredDexOpt = new HashSet<PackageParser.Package>(); @@ -4003,10 +4053,12 @@ public class PackageManagerService extends IPackageManager.Stub { mDeferredDexOpt.add(pkg); return DEX_OPT_DEFERRED; } else { - Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName); + Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName + + " (instructionSet=" + instructionSet + ")"); + final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg), - pkg.packageName); + pkg.packageName, instructionSet); pkg.mDidDexOpt = true; performed = true; } @@ -4033,17 +4085,58 @@ public class PackageManagerService extends IPackageManager.Stub { return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; } + private String getAppInstructionSet(ApplicationInfo info) { + String instructionSet = getPreferredInstructionSet(); + + if (info.requiredCpuAbi != null) { + instructionSet = VMRuntime.getInstructionSet(info.requiredCpuAbi); + } + + return instructionSet; + } + + private String getAppInstructionSetFromSettings(PackageSetting ps) { + String instructionSet = getPreferredInstructionSet(); + + if (ps.requiredCpuAbiString != null) { + instructionSet = VMRuntime.getInstructionSet(ps.requiredCpuAbiString); + } + + return instructionSet; + } + + private static String getPreferredInstructionSet() { + if (sPreferredInstructionSet == null) { + sPreferredInstructionSet = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]); + } + + return sPreferredInstructionSet; + } + + private static List<String> getAllInstructionSets() { + final String[] allAbis = Build.SUPPORTED_ABIS; + final List<String> allInstructionSets = new ArrayList<String>(allAbis.length); + + for (String abi : allAbis) { + final String instructionSet = VMRuntime.getInstructionSet(abi); + if (!allInstructionSets.contains(instructionSet)) { + allInstructionSets.add(instructionSet); + } + } + + return allInstructionSets; + } + private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer, boolean inclDependencies) { HashSet<String> done; - boolean performed = false; if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) { done = new HashSet<String>(); done.add(pkg.packageName); } else { done = null; } - return performDexOptLI(pkg, forceDex, defer, done); + return performDexOptLI(pkg, null /* instruction set override */, forceDex, defer, done); } private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) { @@ -4147,6 +4240,14 @@ public class PackageManagerService extends IPackageManager.Stub { private boolean updateSharedLibrariesLPw(PackageParser.Package pkg, PackageParser.Package changingLib) { + // We might be upgrading from a version of the platform that did not + // provide per-package native library directories for system apps. + // Fix that up here. + if (isSystemApp(pkg)) { + PackageSetting ps = mSettings.mPackages.get(pkg.applicationInfo.packageName); + setInternalAppNativeLibraryPath(pkg, ps); + } + if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) { if (mTmpSharedLibraries == null || mTmpSharedLibraries.length < mSharedLibraries.size()) { @@ -4313,17 +4414,6 @@ public class PackageManagerService extends IPackageManager.Stub { // writer synchronized (mPackages) { - if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { - // Check all shared libraries and map to their actual file path. - // We only do this here for apps not on a system dir, because those - // are the only ones that can fail an install due to this. We - // will take care of the system apps by updating all of their - // library paths after the scan is done. - if (!updateSharedLibrariesLPw(pkg, null)) { - return null; - } - } - if (pkg.mSharedUserId != null) { suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true); if (suid == null) { @@ -4434,6 +4524,17 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } + if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { + // Check all shared libraries and map to their actual file path. + // We only do this here for apps not on a system dir, because those + // are the only ones that can fail an install due to this. We + // will take care of the system apps by updating all of their + // library paths after the scan is done. + if (!updateSharedLibrariesLPw(pkg, null)) { + return null; + } + } + if (mFoundPolicyFile) { SELinuxMMAC.assignSeinfoValue(pkg); } @@ -4534,7 +4635,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (dataPath.exists()) { int currentUid = 0; try { - StructStat stat = Libcore.os.stat(dataPath.getPath()); + StructStat stat = Os.stat(dataPath.getPath()); currentUid = stat.st_uid; } catch (ErrnoException e) { Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e); @@ -4660,7 +4761,6 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString; } } - pkgSetting.uidError = uidError; } @@ -4692,6 +4792,8 @@ public class PackageManagerService extends IPackageManager.Stub { Log.i(TAG, "removed obsolete native libraries for system package " + path); } + + setInternalAppAbi(pkg, pkgSetting); } else { if (!isForwardLocked(pkg) && !isExternal(pkg)) { /* @@ -4723,6 +4825,28 @@ public class PackageManagerService extends IPackageManager.Stub { mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; return null; } + } else { + // We don't have to copy the shared libraries if we're in the ASEC container + // but we still need to scan the file to figure out what ABI the app needs. + // + // TODO: This duplicates work done in the default container service. It's possible + // to clean this up but we'll need to change the interface between this service + // and IMediaContainerService (but doing so will spread this logic out, rather + // than centralizing it). + final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile); + final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS); + if (abi >= 0) { + pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_ABIS[abi]; + } else if (abi == PackageManager.NO_NATIVE_LIBRARIES) { + // Note that (non upgraded) system apps will not have any native + // libraries bundled in their APK, but we're guaranteed not to be + // such an app at this point. + pkg.applicationInfo.requiredCpuAbi = null; + } else { + mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; + return null; + } + handle.close(); } if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path); @@ -4795,8 +4919,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (allowed) { if (!mSharedLibraries.containsKey(name)) { - mSharedLibraries.put(name, new SharedLibraryEntry(null, - pkg.packageName)); + mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName)); } else if (!name.equals(pkg.packageName)) { Slog.w(TAG, "Package " + pkg.packageName + " library " + name + " already exists; skipping"); @@ -4865,6 +4988,12 @@ public class PackageManagerService extends IPackageManager.Stub { // writer synchronized (mPackages) { + if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) { + // We don't do this here during boot because we can do it all + // at once after scanning all existing packages. + adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, + true, forceDex, (scanMode & SCAN_DEFER_DEX) != 0); + } // We don't expect installation to fail beyond this point, if ((scanMode&SCAN_MONITOR) != 0) { mAppDirs.put(pkg.mPath, pkg); @@ -5208,6 +5337,55 @@ public class PackageManagerService extends IPackageManager.Stub { return pkg; } + public void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser, + boolean doDexOpt, boolean forceDexOpt, boolean deferDexOpt) { + String requiredInstructionSet = null; + PackageSetting requirer = null; + for (PackageSetting ps : packagesForUser) { + if (ps.requiredCpuAbiString != null) { + final String instructionSet = VMRuntime.getInstructionSet(ps.requiredCpuAbiString); + if (requiredInstructionSet != null) { + if (!instructionSet.equals(requiredInstructionSet)) { + // We have a mismatch between instruction sets (say arm vs arm64). + // + // TODO: We should rescan all the packages in a shared UID to check if + // they do contain shared libs for other ABIs in addition to the ones we've + // already extracted. For example, the package might contain both arm64-v8a + // and armeabi-v7a shared libs, and we'd have chosen arm64-v8a on 64 bit + // devices. + String errorMessage = "Instruction set mismatch, " + requirer.pkg.packageName + + " requires " + requiredInstructionSet + " whereas " + ps.pkg.packageName + + " requires " + instructionSet; + Slog.e(TAG, errorMessage); + + reportSettingsProblem(Log.WARN, errorMessage); + // Give up, don't bother making any other changes to the package settings. + return; + } + } else { + requiredInstructionSet = instructionSet; + requirer = ps; + } + } + } + + if (requiredInstructionSet != null) { + for (PackageSetting ps : packagesForUser) { + if (ps.requiredCpuAbiString == null) { + ps.requiredCpuAbiString = requirer.requiredCpuAbiString; + if (ps.pkg != null) { + ps.pkg.applicationInfo.requiredCpuAbi = requirer.requiredCpuAbiString; + Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.requiredCpuAbiString); + if (doDexOpt) { + performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true); + mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet()); + } + } + } + } + } + } + private void setUpCustomResolverActivity(PackageParser.Package pkg) { synchronized (mPackages) { mResolverReplaced = true; @@ -5232,14 +5410,86 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private String calculateApkRoot(final String codePathString) { + final File codePath = new File(codePathString); + final File codeRoot; + if (FileUtils.contains(Environment.getRootDirectory(), codePath)) { + codeRoot = Environment.getRootDirectory(); + } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) { + codeRoot = Environment.getOemDirectory(); + } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) { + codeRoot = Environment.getVendorDirectory(); + } else { + // Unrecognized code path; take its top real segment as the apk root: + // e.g. /something/app/blah.apk => /something + try { + File f = codePath.getCanonicalFile(); + File parent = f.getParentFile(); // non-null because codePath is a file + File tmp; + while ((tmp = parent.getParentFile()) != null) { + f = parent; + parent = tmp; + } + codeRoot = f; + Slog.w(TAG, "Unrecognized code path " + + codePath + " - using " + codeRoot); + } catch (IOException e) { + // Can't canonicalize the lib path -- shenanigans? + Slog.w(TAG, "Can't canonicalize code path " + codePath); + return Environment.getRootDirectory().getPath(); + } + } + return codeRoot.getPath(); + } + + // This is the initial scan-time determination of how to handle a given + // package for purposes of native library location. private void setInternalAppNativeLibraryPath(PackageParser.Package pkg, PackageSetting pkgSetting) { - final String apkLibPath = getApkName(pkgSetting.codePathString); - final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath(); + // "bundled" here means system-installed with no overriding update + final boolean bundledApk = isSystemApp(pkg) && !isUpdatedSystemApp(pkg); + final String apkName = getApkName(pkg.applicationInfo.sourceDir); + final File libDir; + if (bundledApk) { + // If "/system/lib64/apkname" exists, assume that is the per-package + // native library directory to use; otherwise use "/system/lib/apkname". + String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir); + File lib64 = new File(apkRoot, LIB64_DIR_NAME); + File packLib64 = new File(lib64, apkName); + libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME); + } else { + libDir = mAppLibInstallDir; + } + final String nativeLibraryPath = (new File(libDir, apkName)).getPath(); pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath; pkgSetting.nativeLibraryPathString = nativeLibraryPath; } + // Deduces the required ABI of an upgraded system app. + private void setInternalAppAbi(PackageParser.Package pkg, PackageSetting pkgSetting) { + final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir); + final String apkName = getApkName(pkg.applicationInfo.sourceDir); + + // This is of the form "/system/lib64/<packagename>", "/vendor/lib64/<packagename>" + // or similar. + final File lib64 = new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath()); + final File lib = new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath()); + + // Assume that the bundled native libraries always correspond to the + // most preferred 32 or 64 bit ABI. + if (lib64.exists()) { + pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0]; + pkgSetting.requiredCpuAbiString = Build.SUPPORTED_64_BIT_ABIS[0]; + } else if (lib.exists()) { + pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0]; + pkgSetting.requiredCpuAbiString = Build.SUPPORTED_32_BIT_ABIS[0]; + } else { + // This is the case where the app has no native code. + pkg.applicationInfo.requiredCpuAbi = null; + pkgSetting.requiredCpuAbiString = null; + } + } + private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir) throws IOException { if (!nativeLibraryDir.isDirectory()) { @@ -5250,8 +5500,7 @@ public class PackageManagerService extends IPackageManager.Stub { } try { - Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH - | S_IXOTH); + Os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); } catch (ErrnoException e) { throw new IOException("Cannot chmod native library directory " + nativeLibraryDir.getPath(), e); @@ -7818,7 +8067,8 @@ public class PackageManagerService extends IPackageManager.Stub { int mRet; MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags, - String packageName, String dataDir, int uid, UserHandle user) { + String packageName, String dataDir, String instructionSet, + int uid, UserHandle user) { super(user); this.srcArgs = srcArgs; this.observer = observer; @@ -7827,7 +8077,7 @@ public class PackageManagerService extends IPackageManager.Stub { this.uid = uid; if (srcArgs != null) { Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath())); - targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir); + targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir, instructionSet); } else { targetArgs = null; } @@ -7936,7 +8186,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath, - String nativeLibraryPath) { + String nativeLibraryPath, String instructionSet) { final boolean isInAsec; if (installOnSd(flags)) { /* Apps on SD card are always in ASEC containers. */ @@ -7954,21 +8204,23 @@ public class PackageManagerService extends IPackageManager.Stub { if (isInAsec) { return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath, - installOnSd(flags), installForwardLocked(flags)); + instructionSet, installOnSd(flags), installForwardLocked(flags)); } else { - return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath); + return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath, + instructionSet); } } // Used by package mover - private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) { + private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir, + String instructionSet) { if (installOnSd(flags) || installForwardLocked(flags)) { String cid = getNextCodePath(packageURI.getPath(), pkgName, "/" + AsecInstallArgs.RES_FILE_NAME); - return new AsecInstallArgs(packageURI, cid, installOnSd(flags), + return new AsecInstallArgs(packageURI, cid, instructionSet, installOnSd(flags), installForwardLocked(flags)); } else { - return new FileInstallArgs(packageURI, pkgName, dataDir); + return new FileInstallArgs(packageURI, pkgName, dataDir, instructionSet); } } @@ -7980,16 +8232,18 @@ public class PackageManagerService extends IPackageManager.Stub { final String installerPackageName; final ManifestDigest manifestDigest; final UserHandle user; + final String instructionSet; InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, ManifestDigest manifestDigest, - UserHandle user) { + UserHandle user, String instructionSet) { this.packageURI = packageURI; this.flags = flags; this.observer = observer; this.installerPackageName = installerPackageName; this.manifestDigest = manifestDigest; this.user = user; + this.instructionSet = instructionSet; } abstract void createCopyFile(); @@ -8045,11 +8299,12 @@ public class PackageManagerService extends IPackageManager.Stub { FileInstallArgs(InstallParams params) { super(params.getPackageUri(), params.observer, params.flags, params.installerPackageName, params.getManifestDigest(), - params.getUser()); + params.getUser(), null /* instruction set */); } - FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) { - super(null, null, 0, null, null, null); + FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath, + String instructionSet) { + super(null, null, 0, null, null, null, instructionSet); File codeFile = new File(fullCodePath); installDir = codeFile.getParentFile(); codeFileName = fullCodePath; @@ -8057,8 +8312,8 @@ public class PackageManagerService extends IPackageManager.Stub { libraryPath = nativeLibraryPath; } - FileInstallArgs(Uri packageURI, String pkgName, String dataDir) { - super(packageURI, null, 0, null, null, null); + FileInstallArgs(Uri packageURI, String pkgName, String dataDir, String instructionSet) { + super(packageURI, null, 0, null, null, null, instructionSet); installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir; String apkName = getNextCodePath(null, pkgName, ".apk"); codeFileName = new File(installDir, apkName + ".apk").getPath(); @@ -8317,7 +8572,10 @@ public class PackageManagerService extends IPackageManager.Stub { void cleanUpResourcesLI() { String sourceDir = getCodePath(); if (cleanUp()) { - int retCode = mInstaller.rmdex(sourceDir); + if (instructionSet == null) { + throw new IllegalStateException("instructionSet == null"); + } + int retCode = mInstaller.rmdex(sourceDir, instructionSet); if (retCode < 0) { Slog.w(TAG, "Couldn't remove dex file for package: " + " at location " @@ -8381,14 +8639,14 @@ public class PackageManagerService extends IPackageManager.Stub { AsecInstallArgs(InstallParams params) { super(params.getPackageUri(), params.observer, params.flags, params.installerPackageName, params.getManifestDigest(), - params.getUser()); + params.getUser(), null /* instruction set */); } AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath, - boolean isExternal, boolean isForwardLocked) { + String instructionSet, boolean isExternal, boolean isForwardLocked) { super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0) | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), - null, null, null); + null, null, null, instructionSet); // Extract cid from fullCodePath int eidx = fullCodePath.lastIndexOf("/"); String subStr1 = fullCodePath.substring(0, eidx); @@ -8397,18 +8655,19 @@ public class PackageManagerService extends IPackageManager.Stub { setCachePath(subStr1); } - AsecInstallArgs(String cid, boolean isForwardLocked) { + AsecInstallArgs(String cid, String instructionSet, boolean isForwardLocked) { super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0) | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), - null, null, null); + null, null, null, instructionSet); this.cid = cid; setCachePath(PackageHelper.getSdDir(cid)); } - AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) { + AsecInstallArgs(Uri packageURI, String cid, String instructionSet, + boolean isExternal, boolean isForwardLocked) { super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0) | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0), - null, null, null); + null, null, null, instructionSet); this.cid = cid; } @@ -8589,7 +8848,10 @@ public class PackageManagerService extends IPackageManager.Stub { void cleanUpResourcesLI() { String sourceFile = getCodePath(); // Remove dex file - int retCode = mInstaller.rmdex(sourceFile); + if (instructionSet == null) { + throw new IllegalStateException("instructionSet == null"); + } + int retCode = mInstaller.rmdex(sourceFile, instructionSet); if (retCode < 0) { Slog.w(TAG, "Couldn't remove dex file for package: " + " at location " @@ -8970,7 +9232,8 @@ public class PackageManagerService extends IPackageManager.Stub { res.removedInfo.args = createInstallArgs(0, deletedPackage.applicationInfo.sourceDir, deletedPackage.applicationInfo.publicSourceDir, - deletedPackage.applicationInfo.nativeLibraryDir); + deletedPackage.applicationInfo.nativeLibraryDir, + getAppInstructionSet(deletedPackage.applicationInfo)); } else { res.removedInfo.args = null; } @@ -9019,7 +9282,8 @@ public class PackageManagerService extends IPackageManager.Stub { private int moveDexFilesLI(PackageParser.Package newPackage) { int retCode; if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) { - retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath); + retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath, + getAppInstructionSet(newPackage.applicationInfo)); if (retCode != 0) { if (mNoDexOpt) { /* @@ -9643,13 +9907,14 @@ public class PackageManagerService extends IPackageManager.Stub { } // writer synchronized (mPackages) { + PackageSetting ps = mSettings.mPackages.get(newPkg.packageName); + setInternalAppNativeLibraryPath(newPkg, ps); updatePermissionsLPw(newPkg.packageName, newPkg, UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); if (applyUserRestrictions) { if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across reinstall"); } - PackageSetting ps = mSettings.mPackages.get(newPkg.packageName); for (int i = 0; i < allUserHandles.length; i++) { if (DEBUG_REMOVE) { Slog.d(TAG, " user " + allUserHandles[i] @@ -9683,7 +9948,8 @@ public class PackageManagerService extends IPackageManager.Stub { // Delete application code and resources if (deleteCodeAndResources && (outInfo != null)) { outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString, - ps.resourcePathString, ps.nativeLibraryPathString); + ps.resourcePathString, ps.nativeLibraryPathString, + getAppInstructionSetFromSettings(ps)); } return true; } @@ -10050,9 +10316,10 @@ public class PackageManagerService extends IPackageManager.Stub { boolean dataOnly = false; String libDirPath = null; String asecPath = null; + PackageSetting ps = null; synchronized (mPackages) { p = mPackages.get(packageName); - PackageSetting ps = mSettings.mPackages.get(packageName); + ps = mSettings.mPackages.get(packageName); if(p == null) { dataOnly = true; if((ps == null) || (ps.pkg == null)) { @@ -10083,7 +10350,8 @@ public class PackageManagerService extends IPackageManager.Stub { } } int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, libDirPath, - publicSrcDir, asecPath, pStats); + publicSrcDir, asecPath, getAppInstructionSetFromSettings(ps), + pStats); if (res < 0) { return false; } @@ -11149,7 +11417,9 @@ public class PackageManagerService extends IPackageManager.Stub { continue; } - final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps)); + final AsecInstallArgs args = new AsecInstallArgs(cid, + getAppInstructionSetFromSettings(ps), + isForwardLocked(ps)); // The package status is changed only if the code path // matches between settings and the container id. if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) { @@ -11464,15 +11734,17 @@ public class PackageManagerService extends IPackageManager.Stub { * anyway. */ if (returnCode != PackageManager.MOVE_SUCCEEDED) { - processPendingMove(new MoveParams(null, observer, 0, packageName, + processPendingMove(new MoveParams(null, observer, 0, packageName, null, null, -1, user), returnCode); } else { Message msg = mHandler.obtainMessage(INIT_COPY); + final String instructionSet = getAppInstructionSet(pkg.applicationInfo); InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir, - pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir); + pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir, + instructionSet); MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName, - pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user); + pkg.applicationInfo.dataDir, instructionSet, pkg.applicationInfo.uid, user); msg.obj = mp; mHandler.sendMessage(msg); } diff --git a/services/java/com/android/server/pm/SELinuxMMAC.java b/services/java/com/android/server/pm/SELinuxMMAC.java index af7153fce0b1..d70c725c8990 100644 --- a/services/java/com/android/server/pm/SELinuxMMAC.java +++ b/services/java/com/android/server/pm/SELinuxMMAC.java @@ -28,7 +28,6 @@ import com.android.internal.util.XmlUtils; import libcore.io.IoUtils; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java index a50c689d0643..dad30e4365f8 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/java/com/android/server/pm/Settings.java @@ -36,6 +36,7 @@ import com.android.internal.util.JournaledFile; import com.android.internal.util.XmlUtils; import com.android.server.pm.PackageManagerService.DumpState; +import java.util.Collection; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -262,6 +263,11 @@ final class Settings { return s; } + Collection<SharedUserSetting> getAllSharedUsersLPw() { + return mSharedUsers.values(); + } + + boolean disableSystemPackageLPw(String name) { final PackageSetting p = mPackages.get(name); if(p == null) { diff --git a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java index e43081436324..3c960c74632b 100644 --- a/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java +++ b/services/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java @@ -18,10 +18,10 @@ package com.android.server.updates; import android.content.Context; import android.content.Intent; -import android.os.FileUtils; -import android.os.SELinux; import android.os.SystemProperties; import android.provider.Settings; +import android.system.ErrnoException; +import android.system.Os; import android.util.Base64; import android.util.Slog; @@ -30,9 +30,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import libcore.io.ErrnoException; import libcore.io.IoUtils; -import libcore.io.Libcore; public class SELinuxPolicyInstallReceiver extends ConfigUpdateInstallReceiver { @@ -112,16 +110,16 @@ public class SELinuxPolicyInstallReceiver extends ConfigUpdateInstallReceiver { File update = new File(updateDir.getParentFile(), "update"); File tmp = new File(updateDir.getParentFile(), "tmp"); if (current.exists()) { - Libcore.os.symlink(updateDir.getPath(), update.getPath()); - Libcore.os.rename(update.getPath(), current.getPath()); + Os.symlink(updateDir.getPath(), update.getPath()); + Os.rename(update.getPath(), current.getPath()); } else { - Libcore.os.symlink(updateDir.getPath(), current.getPath()); + Os.symlink(updateDir.getPath(), current.getPath()); } contexts.mkdirs(); backupContexts(contexts); copyUpdate(contexts); - Libcore.os.symlink(contexts.getPath(), tmp.getPath()); - Libcore.os.rename(tmp.getPath(), current.getPath()); + Os.symlink(contexts.getPath(), tmp.getPath()); + Os.rename(tmp.getPath(), current.getPath()); SystemProperties.set("selinux.reload_policy", "1"); } diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 606fcb4239e5..1ee390fb90b3 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -797,6 +797,8 @@ public class ServiceState implements Parcelable { return TelephonyManager.NETWORK_TYPE_LTE; case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP: return TelephonyManager.NETWORK_TYPE_HSPAP; + case ServiceState.RIL_RADIO_TECHNOLOGY_GSM: + return TelephonyManager.NETWORK_TYPE_GSM; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index ea22bc48fc4a..612f327644e1 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -872,6 +872,8 @@ public class TelephonyManager { public static final int NETWORK_TYPE_EHRPD = 14; /** Current network is HSPA+ */ public static final int NETWORK_TYPE_HSPAP = 15; + /** Current network is GSM {@hide} */ + public static final int NETWORK_TYPE_GSM = 16; /** * @return the NETWORK_TYPE_xxxx for current data connection. @@ -963,6 +965,7 @@ public class TelephonyManager { public static int getNetworkClass(int networkType) { switch (networkType) { case NETWORK_TYPE_GPRS: + case NETWORK_TYPE_GSM: case NETWORK_TYPE_EDGE: case NETWORK_TYPE_CDMA: case NETWORK_TYPE_1xRTT: @@ -1029,6 +1032,8 @@ public class TelephonyManager { return "iDEN"; case NETWORK_TYPE_HSPAP: return "HSPA+"; + case NETWORK_TYPE_GSM: + return "GSM"; default: return "UNKNOWN"; } @@ -1055,6 +1060,10 @@ public class TelephonyManager { public static final int SIM_STATE_NETWORK_LOCKED = 4; /** SIM card state: Ready */ public static final int SIM_STATE_READY = 5; + /** SIM card state: SIM Card Error, Sim Card is present but faulty + *@hide + */ + public static final int SIM_STATE_CARD_IO_ERROR = 6; /** * @return true if a ICC card is present @@ -1081,6 +1090,7 @@ public class TelephonyManager { * @see #SIM_STATE_PUK_REQUIRED * @see #SIM_STATE_NETWORK_LOCKED * @see #SIM_STATE_READY + * @see #SIM_STATE_CARD_IO_ERROR */ public int getSimState() { String prop = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE); @@ -1099,6 +1109,9 @@ public class TelephonyManager { else if ("READY".equals(prop)) { return SIM_STATE_READY; } + else if ("CARD_IO_ERROR".equals(prop)) { + return SIM_STATE_CARD_IO_ERROR; + } else { return SIM_STATE_UNKNOWN; } diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java index 236bb2fb5a57..80297132ab7b 100644 --- a/telephony/java/com/android/internal/telephony/IccCardConstants.java +++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java @@ -28,6 +28,8 @@ public class IccCardConstants { public static final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY"; /* ABSENT means ICC is missing */ public static final String INTENT_VALUE_ICC_ABSENT = "ABSENT"; + /* CARD_IO_ERROR means for three consecutive times there was SIM IO error */ + static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = "CARD_IO_ERROR"; /* LOCKED means ICC is locked by pin or by network */ public static final String INTENT_VALUE_ICC_LOCKED = "LOCKED"; /* READY means ICC is ready to access */ @@ -63,7 +65,8 @@ public class IccCardConstants { NETWORK_LOCKED, READY, NOT_READY, - PERM_DISABLED; + PERM_DISABLED, + CARD_IO_ERROR; public boolean isPinLocked() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)); @@ -72,7 +75,7 @@ public class IccCardConstants { public boolean iccCardExist() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED) || (this == NETWORK_LOCKED) || (this == READY) - || (this == PERM_DISABLED)); + || (this == PERM_DISABLED) || (this == CARD_IO_ERROR)); } } } diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 26b5bd6401e8..cf271a9e1ac8 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -865,6 +865,21 @@ status_t compileResourceFile(Bundle* bundle, pseudoBidiParams.country[0] = 'X'; pseudoBidiParams.country[1] = 'B'; + // We should skip resources for pseudolocales if they were + // already added automatically. This is a fix for a transition period when + // manually pseudolocalized resources may be expected. + // TODO: remove this check after next SDK version release. + if ((bundle->getPseudolocalize() & PSEUDO_ACCENTED && + curParams.locale == pseudoParams.locale) || + (bundle->getPseudolocalize() & PSEUDO_BIDI && + curParams.locale == pseudoBidiParams.locale)) { + SourcePos(in->getPrintableSource(), 0).warning( + "Resource file %s is skipped as pseudolocalization" + " was done automatically.", + in->getPrintableSource().string()); + return NO_ERROR; + } + while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { if (code == ResXMLTree::START_TAG) { const String16* curTag = NULL; @@ -1340,7 +1355,6 @@ status_t compileResourceFile(Bundle* bundle, name, locale, SourcePos(in->getPrintableSource(), block.getLineNumber())); - curIsPseudolocalizable = fileIsTranslatable; } if (formatted == false16) { @@ -1352,7 +1366,7 @@ status_t compileResourceFile(Bundle* bundle, curType = string16; curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING; curIsStyled = true; - curIsPseudolocalizable = (translatable != false16); + curIsPseudolocalizable = fileIsTranslatable && (translatable != false16); } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) { curTag = &drawable16; curType = drawable16; diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java index 998b08b1b359..0f66fd7e6d87 100644 --- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java +++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java @@ -247,4 +247,14 @@ public class ICU_Delegate { return true; } + + @LayoutlibDelegate + /*package*/ static void setDefaultLocale(String locale) { + ICU.setDefaultLocale(locale); + } + + @LayoutlibDelegate + /*package*/ static String getDefaultLocale() { + return ICU.getDefaultLocale(); + } } |