diff options
Diffstat (limited to 'core/java/android')
27 files changed, 484 insertions, 211 deletions
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java index a292ecb..a8896c2 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/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 67c772b..70a3797 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 cb0737e..477285d 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/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 9c46d96..1a1610d 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -441,6 +441,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public String nativeLibraryDir; /** + * The ABI that this application requires, This is inferred from the ABIs + * of the native JNI libraries the application bundles. Will be {@code null} + * if this application does not require any particular ABI. + * + * {@hide} + */ + public String requiredCpuAbi; + + /** * The kernel user-ID that has been assigned to this application; * currently this is not a unique ID (multiple applications can have * the same uid). @@ -570,6 +579,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { sourceDir = orig.sourceDir; publicSourceDir = orig.publicSourceDir; nativeLibraryDir = orig.nativeLibraryDir; + requiredCpuAbi = orig.requiredCpuAbi; resourceDirs = orig.resourceDirs; seinfo = orig.seinfo; sharedLibraryFiles = orig.sharedLibraryFiles; @@ -610,6 +620,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeString(sourceDir); dest.writeString(publicSourceDir); dest.writeString(nativeLibraryDir); + dest.writeString(requiredCpuAbi); dest.writeStringArray(resourceDirs); dest.writeString(seinfo); dest.writeStringArray(sharedLibraryFiles); @@ -649,6 +660,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { sourceDir = source.readString(); publicSourceDir = source.readString(); nativeLibraryDir = source.readString(); + requiredCpuAbi = source.readString(); resourceDirs = source.readStringArray(); seinfo = source.readString(); sharedLibraryFiles = source.readStringArray(); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index c97c2b8..8ce7e97 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -675,6 +675,25 @@ public abstract class PackageManager { public static final int INSTALL_FAILED_USER_RESTRICTED = -111; /** + * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the system failed to install the package because its packaged native code did not + * match any of the ABIs supported by the system. + * + * @hide + */ + public static final int INSTALL_FAILED_NO_MATCHING_ABIS = -112; + + /** + * Internal return code for NativeLibraryHelper methods to indicate that the package + * being processed did not contain any native code. This is placed here only so that + * it can belong to the same value space as the other install failure codes. + * + * @hide + */ + public static final int NO_NATIVE_LIBRARIES = -113; + + /** * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the * package's data directory. * diff --git a/core/java/android/ddm/DdmHandleHeap.java b/core/java/android/ddm/DdmHandleHeap.java index cece556..e24aeb2 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 22543e3..a725bec 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 119e533..643e8c2 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/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java index a28b5a7..d06355d 100644 --- a/core/java/android/net/http/CertificateChainValidator.java +++ b/core/java/android/net/http/CertificateChainValidator.java @@ -22,6 +22,8 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.lang.reflect.Method; import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; import java.security.cert.CertificateException; @@ -74,13 +76,16 @@ public class CertificateChainValidator { private CertificateChainValidator() { try { TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509"); + tmf.init((KeyStore) null); for (TrustManager tm : tmf.getTrustManagers()) { if (tm instanceof X509ExtendedTrustManager) { mTrustManager = (X509ExtendedTrustManager) tm; } } } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("X.509 TrustManager factory must be available", e); + throw new RuntimeException("X.509 TrustManagerFactory must be available", e); + } catch (KeyStoreException e) { + throw new RuntimeException("X.509 TrustManagerFactory cannot be initialized", e); } if (mTrustManager == null) { @@ -166,9 +171,13 @@ public class CertificateChainValidator { TrustManagerFactory tmf; try { tmf = TrustManagerFactory.getInstance("X.509"); + tmf.init((KeyStore) null); } catch (NoSuchAlgorithmException e) { Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory"); return; + } catch (KeyStoreException e) { + Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e); + return; } TrustManager[] tms = tmf.getTrustManagers(); diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java index 666832a..d730a7b 100644 --- a/core/java/android/net/http/X509TrustManagerExtensions.java +++ b/core/java/android/net/http/X509TrustManagerExtensions.java @@ -56,7 +56,8 @@ public class X509TrustManagerExtensions { if (tm instanceof TrustManagerImpl) { mDelegate = (TrustManagerImpl) tm; } else { - throw new IllegalArgumentException("tm is not a supported type of X509TrustManager"); + throw new IllegalArgumentException("tm is an instance of " + tm.getClass().getName() + + " which is not a supported type of X509TrustManager"); } } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 22e1476..b2e0b29 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -74,7 +74,14 @@ public class Build { /** A hardware serial number, if available. Alphanumeric only, case-insensitive. */ public static final String SERIAL = getString("ro.serialno"); - + + /** + * A list of ABIs (in priority) order supported by this device. + * + * @hide + */ + public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").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 3a1da97..7f41c5d 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 20755d9..ba060b8 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/FileUtils.java b/core/java/android/os/FileUtils.java index ff3e277..411783d 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; } diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java index ee7a4c6..6cec55a 100644 --- a/core/java/android/os/MemoryFile.java +++ b/core/java/android/os/MemoryFile.java @@ -63,12 +63,17 @@ public class MemoryFile * Allocates a new ashmem region. The region is initially not purgable. * * @param name optional name for the file (can be null). - * @param length of the memory file in bytes. + * @param length of the memory file in bytes, must be non-negative. * @throws IOException if the memory file could not be created. */ public MemoryFile(String name, int length) throws IOException { mLength = length; - mFD = native_open(name, length); + if (length >= 0) { + mFD = native_open(name, length); + } else { + throw new IOException("Invalid length: " + length); + } + if (length > 0) { mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE); } else { diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java index 5273c20..59795da 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 631edd6..5dc4058 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -16,18 +16,19 @@ package android.os; -import android.net.LocalSocketAddress; import android.net.LocalSocket; +import android.net.LocalSocketAddress; +import android.system.Os; import android.util.Log; -import dalvik.system.Zygote; - +import com.android.internal.os.Zygote; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.IOException; import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; - -import libcore.io.Libcore; +import java.util.Arrays; +import java.util.List; /*package*/ class ZygoteStartFailedEx extends Exception { /** @@ -47,17 +48,7 @@ public class Process { private static final String ZYGOTE_SOCKET = "zygote"; - /** - * Name of a process for running the platform's media services. - * {@hide} - */ - public static final String ANDROID_SHARED_MEDIA = "com.android.process.media"; - - /** - * Name of the process that Google content providers can share. - * {@hide} - */ - public static final String GOOGLE_SHARED_APP_CONTENT = "com.google.process.content"; + private static final String SECONDARY_ZYGOTE_SOCKET = "zygote_secondary"; /** * Defines the UID/GID under which system code runs. @@ -344,15 +335,112 @@ public class Process { public static final int SIGNAL_QUIT = 3; public static final int SIGNAL_KILL = 9; public static final int SIGNAL_USR1 = 10; - - // State for communicating with zygote process - static LocalSocket sZygoteSocket; - static DataInputStream sZygoteInputStream; - static BufferedWriter sZygoteWriter; + /** + * State for communicating with the zygote process. + */ + static class ZygoteState { + final LocalSocket socket; + final DataInputStream inputStream; + final BufferedWriter writer; + final List<String> abiList; - /** true if previous zygote open failed */ - static boolean sPreviousZygoteOpenFailed; + boolean mClosed; + + private ZygoteState(LocalSocket socket, DataInputStream inputStream, + BufferedWriter writer, List<String> abiList) { + this.socket = socket; + this.inputStream = inputStream; + this.writer = writer; + this.abiList = abiList; + } + + static ZygoteState connect(String socketAddress, int tries) throws ZygoteStartFailedEx { + LocalSocket zygoteSocket = null; + DataInputStream zygoteInputStream = null; + BufferedWriter zygoteWriter = null; + + /* + * See bug #811181: Sometimes runtime can make it up before zygote. + * Really, we'd like to do something better to avoid this condition, + * but for now just wait a bit... + * + * TODO: This bug was filed in 2007. Get rid of this code. The zygote + * forks the system_server so it shouldn't be possible for the zygote + * socket to be brought up after the system_server is. + */ + for (int i = 0; i < tries; i++) { + if (i > 0) { + try { + Log.i(LOG_TAG, "Zygote not up yet, sleeping..."); + Thread.sleep(ZYGOTE_RETRY_MILLIS); + } catch (InterruptedException ex) { + throw new ZygoteStartFailedEx(ex); + } + } + + try { + zygoteSocket = new LocalSocket(); + zygoteSocket.connect(new LocalSocketAddress(socketAddress, + LocalSocketAddress.Namespace.RESERVED)); + + zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream()); + + zygoteWriter = new BufferedWriter(new OutputStreamWriter( + zygoteSocket.getOutputStream()), 256); + break; + } catch (IOException ex) { + if (zygoteSocket != null) { + try { + zygoteSocket.close(); + } catch (IOException ex2) { + Log.e(LOG_TAG,"I/O exception on close after exception", ex2); + } + } + + zygoteSocket = null; + } + } + + if (zygoteSocket == null) { + throw new ZygoteStartFailedEx("connect failed"); + } + + String abiListString = getAbiList(zygoteWriter, zygoteInputStream); + Log.i("Zygote", "Process: zygote socket opened, supported ABIS: " + abiListString); + + return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter, + Arrays.asList(abiListString.split(","))); + } + + boolean matches(String abi) { + return abiList.contains(abi); + } + + void close() { + try { + socket.close(); + } catch (IOException ex) { + Log.e(LOG_TAG,"I/O exception on routine close", ex); + } + + mClosed = true; + } + + boolean isClosed() { + return mClosed; + } + } + + /** + * The state of the connection to the primary zygote. + */ + static ZygoteState primaryZygoteState; + + /** + * The state of the connection to the secondary zygote. + */ + static ZygoteState secondaryZygoteState; /** * Start a new process. @@ -378,6 +466,7 @@ public class Process { * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param seInfo null-ok SELinux information for the new process. + * @param abi non-null the ABI this app should be started with. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. @@ -391,10 +480,12 @@ public class Process { int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, + String abi, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, - debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs); + debugFlags, mountExternal, targetSdkVersion, seInfo, + abi, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); @@ -407,78 +498,31 @@ public class Process { static final int ZYGOTE_RETRY_MILLIS = 500; /** - * Tries to open socket to Zygote process if not already open. If - * already open, does nothing. May block and retry. + * Queries the zygote for the list of ABIS it supports. + * + * @throws ZygoteStartFailedEx if the query failed. */ - private static void openZygoteSocketIfNeeded() + private static String getAbiList(BufferedWriter writer, DataInputStream inputStream) throws ZygoteStartFailedEx { + try { - int retryCount; - - if (sPreviousZygoteOpenFailed) { - /* - * If we've failed before, expect that we'll fail again and - * don't pause for retries. - */ - retryCount = 0; - } else { - retryCount = 10; - } - - /* - * See bug #811181: Sometimes runtime can make it up before zygote. - * Really, we'd like to do something better to avoid this condition, - * but for now just wait a bit... - */ - for (int retry = 0 - ; (sZygoteSocket == null) && (retry < (retryCount + 1)) - ; retry++ ) { - - if (retry > 0) { - try { - Log.i("Zygote", "Zygote not up yet, sleeping..."); - Thread.sleep(ZYGOTE_RETRY_MILLIS); - } catch (InterruptedException ex) { - // should never happen - } - } - - try { - sZygoteSocket = new LocalSocket(); - - sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, - LocalSocketAddress.Namespace.RESERVED)); - - sZygoteInputStream - = new DataInputStream(sZygoteSocket.getInputStream()); - - sZygoteWriter = - new BufferedWriter( - new OutputStreamWriter( - sZygoteSocket.getOutputStream()), - 256); - - Log.i("Zygote", "Process: zygote socket opened"); - - sPreviousZygoteOpenFailed = false; - break; - } catch (IOException ex) { - if (sZygoteSocket != null) { - try { - sZygoteSocket.close(); - } catch (IOException ex2) { - Log.e(LOG_TAG,"I/O exception on close after exception", - ex2); - } - } - - sZygoteSocket = null; - } - } - - if (sZygoteSocket == null) { - sPreviousZygoteOpenFailed = true; - throw new ZygoteStartFailedEx("connect failed"); + // Each query starts with the argument count (1 in this case) + writer.write("1"); + // ... followed by a new-line. + writer.newLine(); + // ... followed by our only argument. + writer.write("--query-abi-list"); + writer.newLine(); + writer.flush(); + + // The response is a length prefixed stream of ASCII bytes. + int numBytes = inputStream.readInt(); + byte[] bytes = new byte[numBytes]; + inputStream.readFully(bytes); + + return new String(bytes, StandardCharsets.US_ASCII); + } catch (IOException ioe) { + throw new ZygoteStartFailedEx(ioe); } } @@ -486,14 +530,12 @@ public class Process { * Sends an argument list to the zygote process, which starts a new child * and returns the child's pid. Please note: the present implementation * replaces newlines in the argument list with spaces. - * @param args argument list - * @return An object that describes the result of the attempt to start the process. + * * @throws ZygoteStartFailedEx if process start failed for any reason */ - private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args) + private static ProcessStartResult zygoteSendArgsAndGetResult( + ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { - openZygoteSocketIfNeeded(); - try { /** * See com.android.internal.os.ZygoteInit.readArgumentList() @@ -505,9 +547,11 @@ public class Process { * the child or -1 on failure, followed by boolean to * indicate whether a wrapper process was used. */ + final BufferedWriter writer = zygoteState.writer; + final DataInputStream inputStream = zygoteState.inputStream; - sZygoteWriter.write(Integer.toString(args.size())); - sZygoteWriter.newLine(); + writer.write(Integer.toString(args.size())); + writer.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { @@ -516,32 +560,22 @@ public class Process { throw new ZygoteStartFailedEx( "embedded newlines not allowed"); } - sZygoteWriter.write(arg); - sZygoteWriter.newLine(); + writer.write(arg); + writer.newLine(); } - sZygoteWriter.flush(); + writer.flush(); // Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult(); - result.pid = sZygoteInputStream.readInt(); + result.pid = inputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } - result.usingWrapper = sZygoteInputStream.readBoolean(); + result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { - try { - if (sZygoteSocket != null) { - sZygoteSocket.close(); - } - } catch (IOException ex2) { - // we're going to fail anyway - Log.e(LOG_TAG,"I/O exception on routine close", ex2); - } - - sZygoteSocket = null; - + zygoteState.close(); throw new ZygoteStartFailedEx(ex); } } @@ -558,6 +592,7 @@ public class Process { * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param seInfo null-ok SELinux information for the new process. + * @param abi the ABI the process should use. * @param extraArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason @@ -569,6 +604,7 @@ public class Process { int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, + String abi, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { @@ -636,10 +672,64 @@ public class Process { } } - return zygoteSendArgsAndGetResult(argsForZygote); + return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } } - + + /** + * Returns the number of times we attempt a connection to the zygote. We + * sleep for {@link #ZYGOTE_RETRY_MILLIS} milliseconds between each try. + * + * This could probably be removed, see TODO in {@code ZygoteState#connect}. + */ + private static int getNumTries(ZygoteState state) { + // Retry 10 times for the first connection to each zygote. + if (state == null) { + return 11; + } + + // This means the connection has already been established, but subsequently + // closed, possibly due to an IOException. We retry just once if that's the + // case. + return 1; + } + + /** + * Tries to open socket to Zygote process if not already open. If + * already open, does nothing. May block and retry. + */ + private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { + if (primaryZygoteState == null || primaryZygoteState.isClosed()) { + primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET, getNumTries(primaryZygoteState)); + } + + if (primaryZygoteState.matches(abi)) { + 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, + getNumTries(secondaryZygoteState)); + } + + if (secondaryZygoteState.matches(abi)) { + return secondaryZygoteState; + } + + throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); + } + /** * Returns elapsed milliseconds of the time this process has run. * @return Returns the number of milliseconds this process has return. @@ -651,7 +741,7 @@ public class Process { * {@link #killProcess} and {@link #sendSignal}. */ public static final int myPid() { - return Libcore.os.getpid(); + return Os.getpid(); } /** @@ -659,7 +749,7 @@ public class Process { * @hide */ public static final int myPpid() { - return Libcore.os.getppid(); + return Os.getppid(); } /** @@ -667,7 +757,7 @@ public class Process { * {@link #setThreadPriority(int, int)}. */ public static final int myTid() { - return Libcore.os.gettid(); + return Os.gettid(); } /** @@ -677,7 +767,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 9e9521a..13e9a15 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 f0520b5..6519f7e 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; @@ -697,7 +697,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); @@ -723,7 +723,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 29c0ba2..aefced8 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/util/Log.java b/core/java/android/util/Log.java index abd173a..2b81072 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -352,6 +352,7 @@ public final class Log { /** @hide */ public static final int LOG_ID_RADIO = 1; /** @hide */ public static final int LOG_ID_EVENTS = 2; /** @hide */ public static final int LOG_ID_SYSTEM = 3; + /** @hide */ public static final int LOG_ID_CRASH = 4; /** @hide */ public static native int println_native(int bufID, int priority, String tag, String msg); diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index aa43bad..cd905fa 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -591,6 +591,7 @@ public abstract class LayoutInflater { Object[] args = mConstructorArgs; args[1] = attrs; + constructor.setAccessible(true); final View view = constructor.newInstance(args); if (view instanceof ViewStub) { // always use ourselves when inflating ViewStub later diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index d779628..5b2a452 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -656,7 +656,7 @@ public final class ViewRootImpl implements ViewParent, mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(MSG_FLUSH_LAYER_UPDATES)); } - public boolean attachFunctor(int functor) { + public boolean attachFunctor(long functor) { //noinspection SimplifiableIfStatement if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { return mAttachInfo.mHardwareRenderer.attachFunctor(mAttachInfo, functor); @@ -664,7 +664,7 @@ public final class ViewRootImpl implements ViewParent, return false; } - public void detachFunctor(int functor) { + public void detachFunctor(long functor) { if (mAttachInfo.mHardwareRenderer != null) { mAttachInfo.mHardwareRenderer.detachFunctor(functor); } diff --git a/core/java/android/webkit/ClientCertRequest.java b/core/java/android/webkit/ClientCertRequest.java new file mode 100644 index 0000000..8951786 --- /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 e8974c6..fb842ff 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/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index c0fde2e..26c5732 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -1944,7 +1944,16 @@ public class NumberPicker extends LinearLayout { , '\u0669', // Extended Arabic-Indic '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8' - , '\u06f9' + , '\u06f9', + // Hindi and Marathi (Devanagari script) + '\u0966', '\u0967', '\u0968', '\u0969', '\u096a', '\u096b', '\u096c', '\u096d', '\u096e' + , '\u096f', + // Bengali + '\u09e6', '\u09e7', '\u09e8', '\u09e9', '\u09ea', '\u09eb', '\u09ec', '\u09ed', '\u09ee' + , '\u09ef', + // Kannada + '\u0ce6', '\u0ce7', '\u0ce8', '\u0ce9', '\u0cea', '\u0ceb', '\u0cec', '\u0ced', '\u0cee' + , '\u0cef' }; /** diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 37121e2..5ece016 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5147,12 +5147,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int width = mRight - mLeft; final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight(); final float dx = mLayout.getLineRight(0) - (width - padding); - canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); } if (mMarquee != null && mMarquee.isRunning()) { final float dx = -mMarquee.getScroll(); - canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); } } @@ -5166,8 +5166,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (mMarquee != null && mMarquee.shouldDrawGhost()) { - final int dx = (int) mMarquee.getGhostOffset(); - canvas.translate(isLayoutRtl ? -dx : dx, 0.0f); + final float dx = mMarquee.getGhostOffset(); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical); } |
