diff options
33 files changed, 1074 insertions, 393 deletions
diff --git a/api/current.txt b/api/current.txt index 22c9afd303f6..8d650cb51ed9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26520,6 +26520,7 @@ package android.renderscript { public class Script extends android.renderscript.BaseObj { method public void bindAllocation(android.renderscript.Allocation, int); method protected android.renderscript.Script.FieldID createFieldID(int, android.renderscript.Element); + method protected android.renderscript.Script.InvokeID createInvokeID(int); method protected android.renderscript.Script.KernelID createKernelID(int, int, android.renderscript.Element, android.renderscript.Element); method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker); method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker, android.renderscript.Script.LaunchOptions); @@ -26560,6 +26561,9 @@ package android.renderscript { public static final class Script.FieldID extends android.renderscript.BaseObj { } + public static final class Script.InvokeID extends android.renderscript.BaseObj { + } + public static final class Script.KernelID extends android.renderscript.BaseObj { } @@ -26584,12 +26588,19 @@ package android.renderscript { } public final class ScriptGroup extends android.renderscript.BaseObj { - method public void execute(); - method public void setInput(android.renderscript.Script.KernelID, android.renderscript.Allocation); - method public void setOutput(android.renderscript.Script.KernelID, android.renderscript.Allocation); + method public java.lang.Object[] execute(java.lang.Object...); + method public deprecated void execute(); + method public deprecated void setInput(android.renderscript.Script.KernelID, android.renderscript.Allocation); + method public deprecated void setOutput(android.renderscript.Script.KernelID, android.renderscript.Allocation); } - public static final class ScriptGroup.Builder { + public static final class ScriptGroup.Binding { + ctor public ScriptGroup.Binding(android.renderscript.Script.FieldID, java.lang.Object); + method public android.renderscript.Script.FieldID getField(); + method public java.lang.Object getValue(); + } + + public static final deprecated class ScriptGroup.Builder { ctor public ScriptGroup.Builder(android.renderscript.RenderScript); method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.FieldID); method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.KernelID); @@ -26597,6 +26608,25 @@ package android.renderscript { method public android.renderscript.ScriptGroup create(); } + public static final class ScriptGroup.Builder2 { + ctor public ScriptGroup.Builder2(android.renderscript.RenderScript); + method public android.renderscript.ScriptGroup.Input addInput(); + method public android.renderscript.ScriptGroup.Closure addInvoke(android.renderscript.Script.InvokeID, java.lang.Object...); + method public android.renderscript.ScriptGroup.Closure addKernel(android.renderscript.Script.KernelID, android.renderscript.Type, java.lang.Object...); + method public android.renderscript.ScriptGroup create(java.lang.String, android.renderscript.ScriptGroup.Future...); + } + + public static final class ScriptGroup.Closure extends android.renderscript.BaseObj { + method public android.renderscript.ScriptGroup.Future getGlobal(android.renderscript.Script.FieldID); + method public android.renderscript.ScriptGroup.Future getReturn(); + } + + public static final class ScriptGroup.Future { + } + + public static final class ScriptGroup.Input { + } + public abstract class ScriptIntrinsic extends android.renderscript.Script { } diff --git a/api/system-current.txt b/api/system-current.txt index 209a526e502c..8af6a956cc89 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -28117,6 +28117,7 @@ package android.renderscript { public class Script extends android.renderscript.BaseObj { method public void bindAllocation(android.renderscript.Allocation, int); method protected android.renderscript.Script.FieldID createFieldID(int, android.renderscript.Element); + method protected android.renderscript.Script.InvokeID createInvokeID(int); method protected android.renderscript.Script.KernelID createKernelID(int, int, android.renderscript.Element, android.renderscript.Element); method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker); method protected void forEach(int, android.renderscript.Allocation, android.renderscript.Allocation, android.renderscript.FieldPacker, android.renderscript.Script.LaunchOptions); @@ -28157,6 +28158,9 @@ package android.renderscript { public static final class Script.FieldID extends android.renderscript.BaseObj { } + public static final class Script.InvokeID extends android.renderscript.BaseObj { + } + public static final class Script.KernelID extends android.renderscript.BaseObj { } @@ -28181,12 +28185,19 @@ package android.renderscript { } public final class ScriptGroup extends android.renderscript.BaseObj { - method public void execute(); - method public void setInput(android.renderscript.Script.KernelID, android.renderscript.Allocation); - method public void setOutput(android.renderscript.Script.KernelID, android.renderscript.Allocation); + method public java.lang.Object[] execute(java.lang.Object...); + method public deprecated void execute(); + method public deprecated void setInput(android.renderscript.Script.KernelID, android.renderscript.Allocation); + method public deprecated void setOutput(android.renderscript.Script.KernelID, android.renderscript.Allocation); } - public static final class ScriptGroup.Builder { + public static final class ScriptGroup.Binding { + ctor public ScriptGroup.Binding(android.renderscript.Script.FieldID, java.lang.Object); + method public android.renderscript.Script.FieldID getField(); + method public java.lang.Object getValue(); + } + + public static final deprecated class ScriptGroup.Builder { ctor public ScriptGroup.Builder(android.renderscript.RenderScript); method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.FieldID); method public android.renderscript.ScriptGroup.Builder addConnection(android.renderscript.Type, android.renderscript.Script.KernelID, android.renderscript.Script.KernelID); @@ -28194,6 +28205,25 @@ package android.renderscript { method public android.renderscript.ScriptGroup create(); } + public static final class ScriptGroup.Builder2 { + ctor public ScriptGroup.Builder2(android.renderscript.RenderScript); + method public android.renderscript.ScriptGroup.Input addInput(); + method public android.renderscript.ScriptGroup.Closure addInvoke(android.renderscript.Script.InvokeID, java.lang.Object...); + method public android.renderscript.ScriptGroup.Closure addKernel(android.renderscript.Script.KernelID, android.renderscript.Type, java.lang.Object...); + method public android.renderscript.ScriptGroup create(java.lang.String, android.renderscript.ScriptGroup.Future...); + } + + public static final class ScriptGroup.Closure extends android.renderscript.BaseObj { + method public android.renderscript.ScriptGroup.Future getGlobal(android.renderscript.Script.FieldID); + method public android.renderscript.ScriptGroup.Future getReturn(); + } + + public static final class ScriptGroup.Future { + } + + public static final class ScriptGroup.Input { + } + public abstract class ScriptIntrinsic extends android.renderscript.Script { } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b063209b3856..e32254a91d1e 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -257,23 +257,18 @@ public final class ActivityThread { } } - static final class AcquiringProviderRecord { - IActivityManager.ContentProviderHolder holder; - boolean acquiring = true; - int requests = 1; - // Set if there was a runtime exception when trying to acquire the provider. - RuntimeException runtimeException = null; - } - // The lock of mProviderMap protects the following variables. - final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap = new ArrayMap<>(); - final ArrayMap<ProviderKey, AcquiringProviderRecord> mAcquiringProviderMap = new ArrayMap<>(); - final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap = new ArrayMap<>(); - final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders = new ArrayMap<>(); - final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName = new ArrayMap<>(); + final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap + = new ArrayMap<ProviderKey, ProviderClientRecord>(); + final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap + = new ArrayMap<IBinder, ProviderRefCount>(); + final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders + = new ArrayMap<IBinder, ProviderClientRecord>(); + final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName + = new ArrayMap<ComponentName, ProviderClientRecord>(); final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners - = new ArrayMap<>(); + = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>(); final GcIdler mGcIdler = new GcIdler(); boolean mGcIdlerScheduled = false; @@ -350,7 +345,7 @@ public final class ActivityThread { } } - static final class ProviderClientRecord { + final class ProviderClientRecord { final String[] mNames; final IContentProvider mProvider; final ContentProvider mLocalProvider; @@ -4653,74 +4648,23 @@ public final class ActivityThread { public final IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable) { - final ProviderKey key = new ProviderKey(auth, userId); - final IContentProvider provider = acquireExistingProvider(c, key, stable); + final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); if (provider != null) { return provider; } - AcquiringProviderRecord r; - boolean first = false; - synchronized (mAcquiringProviderMap) { - r = mAcquiringProviderMap.get(key); - if (r == null) { - r = new AcquiringProviderRecord(); - mAcquiringProviderMap.put(key, r); - first = true; - } else { - r.requests++; - } - } + // There is a possible race here. Another thread may try to acquire + // the same provider at the same time. When this happens, we want to ensure + // that the first one wins. + // Note that we cannot hold the lock while acquiring and installing the + // provider since it might take a long time to run and it could also potentially + // be re-entrant in the case where the provider is in the same process. IActivityManager.ContentProviderHolder holder = null; try { - if (first) { - // Multiple threads may try to acquire the same provider at the same time. - // When this happens, we only let the first one really gets provider. - // Other threads just wait for its result. - // Note that we cannot hold the lock while acquiring and installing the - // provider since it might take a long time to run and it could also potentially - // be re-entrant in the case where the provider is in the same process. - holder = ActivityManagerNative.getDefault().getContentProvider( - getApplicationThread(), auth, userId, stable); - } else { - synchronized (r) { - while (r.acquiring) { - try { - r.wait(); - } catch (InterruptedException e) { - } - } - holder = r.holder; - } - } + holder = ActivityManagerNative.getDefault().getContentProvider( + getApplicationThread(), auth, userId, stable); } catch (RemoteException ex) { - } catch (RuntimeException e) { - synchronized (r) { - r.runtimeException = e; - } - } finally { - if (first) { - synchronized (r) { - r.holder = holder; - r.acquiring = false; - r.notifyAll(); - } - } - - synchronized (mAcquiringProviderMap) { - if (--r.requests == 0) { - mAcquiringProviderMap.remove(key); - } - } - - if (r.runtimeException != null) { - // Was set when the first thread tried to acquire the provider, - // but we should make sure it is thrown for all threads trying to - // acquire the provider. - throw r.runtimeException; - } } - if (holder == null) { Slog.e(TAG, "Failed to find provider info for " + auth); return null; @@ -4803,12 +4747,8 @@ public final class ActivityThread { public final IContentProvider acquireExistingProvider( Context c, String auth, int userId, boolean stable) { - return acquireExistingProvider(c, new ProviderKey(auth, userId), stable); - } - - final IContentProvider acquireExistingProvider( - Context c, ProviderKey key, boolean stable) { synchronized (mProviderMap) { + final ProviderKey key = new ProviderKey(auth, userId); final ProviderClientRecord pr = mProviderMap.get(key); if (pr == null) { return null; @@ -4819,7 +4759,7 @@ public final class ActivityThread { if (!jBinder.isBinderAlive()) { // The hosting process of the provider has died; we can't // use this one. - Log.i(TAG, "Acquiring provider " + key.authority + " for user " + key.userId + Log.i(TAG, "Acquiring provider " + auth + " for user " + userId + ": existing object's process dead"); handleUnstableProviderDiedLocked(jBinder, true); return null; @@ -5141,12 +5081,18 @@ public final class ActivityThread { if (DEBUG_PROVIDER) { Slog.v(TAG, "installProvider: lost the race, updating ref count"); } - // The provider has already been installed, so we need - // to increase reference count to the existing one, but - // only if release is needed (that is, it is not running - // in the system process or local to the process). + // We need to transfer our new reference to the existing + // ref count, releasing the old one... but only if + // release is needed (that is, it is not running in the + // system process). if (!noReleaseNeeded) { incProviderRefLocked(prc, stable); + try { + ActivityManagerNative.getDefault().removeContentProvider( + holder.connection, stable); + } catch (RemoteException e) { + //do nothing content provider object is dead any way + } } } else { ProviderClientRecord client = installProviderAuthoritiesLocked( diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java index 24a7d3327664..3cda39ae9aad 100644 --- a/core/java/android/database/sqlite/SQLiteConnection.java +++ b/core/java/android/database/sqlite/SQLiteConnection.java @@ -91,8 +91,6 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - private static final Pattern TRIM_SQL_PATTERN = Pattern.compile("[\\s]*\\n+[\\s]*"); - private final CloseGuard mCloseGuard = CloseGuard.get(); private final SQLiteConnectionPool mPool; @@ -1203,7 +1201,11 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen } private static String trimSqlForDisplay(String sql) { - return TRIM_SQL_PATTERN.matcher(sql).replaceAll(" "); + // Note: Creating and caching a regular expression is expensive at preload-time + // and stops compile-time initialization. This pattern is only used when + // dumping the connection, which is a rare (mainly error) case. So: + // DO NOT CACHE. + return sql.replaceAll("[\\s]*\\n+[\\s]*", " "); } /** @@ -1437,9 +1439,6 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen } private static final class Operation { - private static final SimpleDateFormat sDateFormat = - new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - public long mStartTime; public long mEndTime; public String mKind; @@ -1494,7 +1493,11 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen } private String getFormattedStartTime() { - return sDateFormat.format(new Date(mStartTime)); + // Note: SimpleDateFormat is not thread-safe, cannot be compile-time created, and is + // relatively expensive to create during preloading. This method is only used + // when dumping a connection, which is a rare (mainly error) case. So: + // DO NOT CACHE. + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(mStartTime)); } } } diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index fb2f445002ee..54532837cec2 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -1657,7 +1657,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { /** * Searches the query string for the first value with the given key. * - * <p><strong>Warning:</strong> Prior to Ice Cream Sandwich, this decoded + * <p><strong>Warning:</strong> Prior to Jelly Bean, this decoded * the '+' character as '+' rather than ' '. * * @param key which will be encoded diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index c5c537263bbd..cb3e22be915b 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -211,8 +211,9 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { } else if (obj instanceof Parcelable[]) { Parcelable[] array = (Parcelable[]) obj; for (int n = array.length - 1; n >= 0; n--) { - if ((array[n].describeContents() - & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) { + Parcelable p = array[n]; + if (p != null && ((p.describeContents() + & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0)) { fdFound = true; break; } @@ -221,7 +222,8 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { SparseArray<? extends Parcelable> array = (SparseArray<? extends Parcelable>) obj; for (int n = array.size() - 1; n >= 0; n--) { - if ((array.valueAt(n).describeContents() + Parcelable p = array.valueAt(n); + if (p != null && (p.describeContents() & Parcelable.CONTENTS_FILE_DESCRIPTOR) != 0) { fdFound = true; break; diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 0de9c702a290..d2eaed368689 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -634,6 +634,9 @@ public class Process { if ((debugFlags & Zygote.DEBUG_ENABLE_JIT) != 0) { argsForZygote.add("--enable-jit"); } + if ((debugFlags & Zygote.DEBUG_GENERATE_CFI) != 0) { + argsForZygote.add("--generate-cfi"); + } if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); } diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index a237afd3d500..27304f59e437 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -1040,14 +1040,10 @@ public class ViewDebug { return methods; } - final ArrayList<Method> declaredMethods = new ArrayList(); - klass.getDeclaredMethodsUnchecked(false, declaredMethods); + methods = klass.getDeclaredMethodsUnchecked(false); final ArrayList<Method> foundMethods = new ArrayList<Method>(); - final int count = declaredMethods.size(); - for (int i = 0; i < count; i++) { - final Method method = declaredMethods.get(i); - + for (final Method method : methods) { // Ensure the method return and parameter types can be resolved. try { method.getReturnType(); diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 8674a2111c18..86ba780acb40 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -40,6 +40,8 @@ public final class Zygote { public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4; /** enable the JIT compiler */ public static final int DEBUG_ENABLE_JIT = 1 << 5; + /** Force generation of CFI code */ + public static final int DEBUG_GENERATE_CFI = 1 << 6; /** No external storage should be mounted. */ diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 0dc242d59419..f43cc62491b4 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -322,7 +322,7 @@ class ZygoteConnection { /** * From --enable-debugger, --enable-checkjni, --enable-assert, - * --enable-safemode, --enable-jit, and --enable-jni-logging. + * --enable-safemode, --enable-jit, --generate-cfi and --enable-jni-logging. */ int debugFlags; @@ -434,6 +434,8 @@ class ZygoteConnection { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } else if (arg.equals("--enable-jit")) { debugFlags |= Zygote.DEBUG_ENABLE_JIT; + } else if (arg.equals("--generate-cfi")) { + debugFlags |= Zygote.DEBUG_GENERATE_CFI; } else if (arg.equals("--enable-jni-logging")) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } else if (arg.equals("--enable-assert")) { diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 50ddbd16ba39..d44959b05d50 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -267,7 +267,12 @@ public class ZygoteInit { if (false) { Log.v(TAG, "Preloading " + line + "..."); } - Class.forName(line); + // Load and explicitly initialize the given class. Use + // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups + // (to derive the caller's class-loader). Use true to force initialization, and + // null for the boot classpath class-loader (could as well cache the + // class-loader of this class in a variable). + Class.forName(line, true, null); count++; } catch (ClassNotFoundException e) { Log.w(TAG, "Class not found for preloading: " + line); diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 0bfc0c96492c..82fe227c1787 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -873,6 +873,19 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) snprintf(cpuAbiListBuf, sizeof(cpuAbiListBuf), "--cpu-abilist=%s", propBuf); addOption(cpuAbiListBuf); + /* + * When running with debug.gencfi, add --include-cfi to the compiler options so that the boot + * image, if it is compiled on device, will include CFI info, as well as other compilations + * started by the runtime. + */ + property_get("debug.gencfi", propBuf, ""); + if (strcmp(propBuf, "true") == 0) { + addOption("-Xcompiler-option"); + addOption("--include-cfi"); + addOption("-Ximage-compiler-option"); + addOption("--include-cfi"); + } + initArgs.version = JNI_VERSION_1_4; initArgs.options = mOptions.editArray(); initArgs.nOptions = mOptions.size(); diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java index 5fae831de8d7..3b25ba66b9c3 100644 --- a/keystore/java/android/security/AndroidKeyPairGenerator.java +++ b/keystore/java/android/security/AndroidKeyPairGenerator.java @@ -17,7 +17,7 @@ package android.security; import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; -import com.android.org.conscrypt.NativeCrypto; +import com.android.org.conscrypt.NativeConstants; import com.android.org.conscrypt.OpenSSLEngine; import java.security.InvalidAlgorithmParameterException; @@ -206,9 +206,9 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { } private static int getDefaultKeySize(int keyType) { - if (keyType == NativeCrypto.EVP_PKEY_EC) { + if (keyType == NativeConstants.EVP_PKEY_EC) { return EC_DEFAULT_KEY_SIZE; - } else if (keyType == NativeCrypto.EVP_PKEY_RSA) { + } else if (keyType == NativeConstants.EVP_PKEY_RSA) { return RSA_DEFAULT_KEY_SIZE; } return -1; @@ -216,12 +216,12 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { private static void checkValidKeySize(String keyAlgorithm, int keyType, int keySize) throws InvalidAlgorithmParameterException { - if (keyType == NativeCrypto.EVP_PKEY_EC) { + if (keyType == NativeConstants.EVP_PKEY_EC) { if (keySize < EC_MIN_KEY_SIZE || keySize > EC_MAX_KEY_SIZE) { throw new InvalidAlgorithmParameterException("EC keys must be >= " + EC_MIN_KEY_SIZE + " and <= " + EC_MAX_KEY_SIZE); } - } else if (keyType == NativeCrypto.EVP_PKEY_RSA) { + } else if (keyType == NativeConstants.EVP_PKEY_RSA) { if (keySize < RSA_MIN_KEY_SIZE || keySize > RSA_MAX_KEY_SIZE) { throw new InvalidAlgorithmParameterException("RSA keys must be >= " + RSA_MIN_KEY_SIZE + " and <= " + RSA_MAX_KEY_SIZE); @@ -234,7 +234,7 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { private static void checkCorrectParametersSpec(int keyType, int keySize, AlgorithmParameterSpec spec) throws InvalidAlgorithmParameterException { - if (keyType == NativeCrypto.EVP_PKEY_RSA && spec != null) { + if (keyType == NativeConstants.EVP_PKEY_RSA && spec != null) { if (spec instanceof RSAKeyGenParameterSpec) { RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) spec; if (keySize != -1 && keySize != rsaSpec.getKeysize()) { @@ -260,7 +260,7 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { private static byte[][] getArgsForKeyType(int keyType, AlgorithmParameterSpec spec) { switch (keyType) { - case NativeCrypto.EVP_PKEY_RSA: + case NativeConstants.EVP_PKEY_RSA: if (spec instanceof RSAKeyGenParameterSpec) { RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) spec; return new byte[][] { rsaSpec.getPublicExponent().toByteArray() }; diff --git a/keystore/java/android/security/CryptoOperationException.java b/keystore/java/android/security/CryptoOperationException.java deleted file mode 100644 index 00c142fbec9d..000000000000 --- a/keystore/java/android/security/CryptoOperationException.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2015 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.security; - -/** - * Base class for exceptions during cryptographic operations which cannot throw a suitable checked - * exception. - * - * <p>The contract of the majority of crypto primitives/operations (e.g. {@code Cipher} or - * {@code Signature}) is that they can throw a checked exception during initialization, but are not - * permitted to throw a checked exception during operation. Because crypto operations can fail - * for a variety of reasons after initialization, this base class provides type-safety for unchecked - * exceptions that may be thrown in those cases. - * - * @hide - */ -public class CryptoOperationException extends RuntimeException { - - /** - * Constructs a new {@code CryptoOperationException} without detail message and cause. - */ - public CryptoOperationException() { - super(); - } - - /** - * Constructs a new {@code CryptoOperationException} with the provided detail message and no - * cause. - */ - public CryptoOperationException(String message) { - super(message); - } - - /** - * Constructs a new {@code CryptoOperationException} with the provided detail message and cause. - */ - public CryptoOperationException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructs a new {@code CryptoOperationException} with the provided cause. - */ - public CryptoOperationException(Throwable cause) { - super(cause); - } -} diff --git a/keystore/java/android/security/KeyExpiredException.java b/keystore/java/android/security/KeyExpiredException.java index 35a5accbc94c..e64bffa481db 100644 --- a/keystore/java/android/security/KeyExpiredException.java +++ b/keystore/java/android/security/KeyExpiredException.java @@ -16,13 +16,15 @@ package android.security; +import java.security.InvalidKeyException; + /** * Indicates that a cryptographic operation failed because the employed key's validity end date * is in the past. * * @hide */ -public class KeyExpiredException extends CryptoOperationException { +public class KeyExpiredException extends InvalidKeyException { /** * Constructs a new {@code KeyExpiredException} without detail message and cause. diff --git a/keystore/java/android/security/KeyNotYetValidException.java b/keystore/java/android/security/KeyNotYetValidException.java index f1c2cac672b9..d36d80c80ca6 100644 --- a/keystore/java/android/security/KeyNotYetValidException.java +++ b/keystore/java/android/security/KeyNotYetValidException.java @@ -16,13 +16,15 @@ package android.security; +import java.security.InvalidKeyException; + /** * Indicates that a cryptographic operation failed because the employed key's validity start date * is in the future. * * @hide */ -public class KeyNotYetValidException extends CryptoOperationException { +public class KeyNotYetValidException extends InvalidKeyException { /** * Constructs a new {@code KeyNotYetValidException} without detail message and cause. diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 84a664e30163..3bc1b1773695 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -16,7 +16,7 @@ package android.security; -import com.android.org.conscrypt.NativeCrypto; +import com.android.org.conscrypt.NativeConstants; import android.os.Binder; import android.os.IBinder; @@ -30,6 +30,7 @@ import android.security.keymaster.KeymasterDefs; import android.security.keymaster.OperationResult; import android.util.Log; +import java.security.InvalidKeyException; import java.util.Locale; /** @@ -87,9 +88,9 @@ public class KeyStore { static int getKeyTypeForAlgorithm(String keyType) { if ("RSA".equalsIgnoreCase(keyType)) { - return NativeCrypto.EVP_PKEY_RSA; + return NativeConstants.EVP_PKEY_RSA; } else if ("EC".equalsIgnoreCase(keyType)) { - return NativeCrypto.EVP_PKEY_EC; + return NativeConstants.EVP_PKEY_EC; } else { return -1; } @@ -508,7 +509,11 @@ public class KeyStore { } } - public static KeyStoreException getKeyStoreException(int errorCode) { + /** + * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error + * code. + */ + static KeyStoreException getKeyStoreException(int errorCode) { if (errorCode > 0) { // KeyStore layer error switch (errorCode) { @@ -544,7 +549,11 @@ public class KeyStore { } } - public static CryptoOperationException getCryptoOperationException(KeyStoreException e) { + /** + * Returns an {@link InvalidKeyException} corresponding to the provided + * {@link KeyStoreException}. + */ + static InvalidKeyException getInvalidKeyException(KeyStoreException e) { switch (e.getErrorCode()) { case KeymasterDefs.KM_ERROR_KEY_EXPIRED: return new KeyExpiredException(); @@ -553,11 +562,15 @@ public class KeyStore { case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: return new UserNotAuthenticatedException(); default: - return new CryptoOperationException("Crypto operation failed", e); + return new InvalidKeyException("Keystore operation failed", e); } } - public static CryptoOperationException getCryptoOperationException(int errorCode) { - return getCryptoOperationException(getKeyStoreException(errorCode)); + /** + * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error + * code. + */ + static InvalidKeyException getInvalidKeyException(int errorCode) { + return getInvalidKeyException(getKeyStoreException(errorCode)); } } diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java index 37e00b28cd83..3b13e83520bb 100644 --- a/keystore/java/android/security/KeyStoreCipherSpi.java +++ b/keystore/java/android/security/KeyStoreCipherSpi.java @@ -136,6 +136,14 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry private Long mOperationHandle; private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer; + /** + * Encountered exception which could not be immediately thrown because it was encountered inside + * a method that does not throw checked exception. This exception will be thrown from + * {@code engineDoFinal}. Once such an exception is encountered, {@code engineUpdate} and + * {@code engineDoFinal} start ignoring input data. + */ + private Exception mCachedException; + protected KeyStoreCipherSpi( int keymasterAlgorithm, int keymasterBlockMode, @@ -152,29 +160,62 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry @Override protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { - init(opmode, key, random); - initAlgorithmSpecificParameters(); - ensureKeystoreOperationInitialized(); + resetAll(); + + boolean success = false; + try { + init(opmode, key, random); + initAlgorithmSpecificParameters(); + try { + ensureKeystoreOperationInitialized(); + } catch (InvalidAlgorithmParameterException e) { + throw new InvalidKeyException(e); + } + success = true; + } finally { + if (!success) { + resetAll(); + } + } } @Override protected void engineInit(int opmode, Key key, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { - init(opmode, key, random); - initAlgorithmSpecificParameters(params); - ensureKeystoreOperationInitialized(); + resetAll(); + + boolean success = false; + try { + init(opmode, key, random); + initAlgorithmSpecificParameters(params); + ensureKeystoreOperationInitialized(); + success = true; + } finally { + if (!success) { + resetAll(); + } + } } @Override protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { - init(opmode, key, random); - initAlgorithmSpecificParameters(params); - ensureKeystoreOperationInitialized(); + resetAll(); + + boolean success = false; + try { + init(opmode, key, random); + initAlgorithmSpecificParameters(params); + ensureKeystoreOperationInitialized(); + success = true; + } finally { + if (!success) { + resetAll(); + } + } } private void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException { - resetAll(); if (!(key instanceof KeyStoreSecretKey)) { throw new InvalidKeyException( "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null")); @@ -207,6 +248,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry mOperationToken = null; mOperationHandle = null; mMainDataStreamer = null; + mCachedException = null; } private void resetWhilePreservingInitState() { @@ -218,12 +260,17 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry mOperationHandle = null; mMainDataStreamer = null; mAdditionalEntropyForBegin = null; + mCachedException = null; } - private void ensureKeystoreOperationInitialized() { + private void ensureKeystoreOperationInitialized() throws InvalidKeyException, + InvalidAlgorithmParameterException { if (mMainDataStreamer != null) { return; } + if (mCachedException != null) { + return; + } if (mKey == null) { throw new IllegalStateException("Not initialized"); } @@ -252,11 +299,15 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry if (opResult == null) { throw new KeyStoreConnectException(); } else if (opResult.resultCode != KeyStore.NO_ERROR) { - throw KeyStore.getCryptoOperationException(opResult.resultCode); + switch (opResult.resultCode) { + case KeymasterDefs.KM_ERROR_INVALID_NONCE: + throw new InvalidAlgorithmParameterException("Invalid IV"); + } + throw KeyStore.getInvalidKeyException(opResult.resultCode); } if (opResult.token == null) { - throw new CryptoOperationException("Keystore returned null operation token"); + throw new IllegalStateException("Keystore returned null operation token"); } mOperationToken = opResult.token; mOperationHandle = opResult.operationHandle; @@ -270,7 +321,15 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry @Override protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { - ensureKeystoreOperationInitialized(); + if (mCachedException != null) { + return null; + } + try { + ensureKeystoreOperationInitialized(); + } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { + mCachedException = e; + return null; + } if (inputLen == 0) { return null; @@ -280,7 +339,8 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry try { output = mMainDataStreamer.update(input, inputOffset, inputLen); } catch (KeyStoreException e) { - throw KeyStore.getCryptoOperationException(e); + mCachedException = e; + return null; } if (output.length == 0) { @@ -309,7 +369,16 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry @Override protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { - ensureKeystoreOperationInitialized(); + if (mCachedException != null) { + throw (IllegalBlockSizeException) + new IllegalBlockSizeException().initCause(mCachedException); + } + + try { + ensureKeystoreOperationInitialized(); + } catch (InvalidKeyException | InvalidAlgorithmParameterException e) { + throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e); + } byte[] output; try { @@ -323,7 +392,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED: throw new AEADBadTagException(); default: - throw KeyStore.getCryptoOperationException(e); + throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e); } } @@ -584,11 +653,11 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry if (mIv == null) { mIv = returnedIv; } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) { - throw new CryptoOperationException("IV in use differs from provided IV"); + throw new IllegalStateException("IV in use differs from provided IV"); } } else { if (returnedIv != null) { - throw new CryptoOperationException( + throw new IllegalStateException( "IV in use despite IV not being used by this transformation"); } } diff --git a/keystore/java/android/security/KeyStoreConnectException.java b/keystore/java/android/security/KeyStoreConnectException.java index 8ed6e04ddfe8..1aa3aecc0b1e 100644 --- a/keystore/java/android/security/KeyStoreConnectException.java +++ b/keystore/java/android/security/KeyStoreConnectException.java @@ -21,7 +21,7 @@ package android.security; * * @hide */ -public class KeyStoreConnectException extends CryptoOperationException { +public class KeyStoreConnectException extends IllegalStateException { public KeyStoreConnectException() { super("Failed to communicate with keystore service"); } diff --git a/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java index aafd2fa97aff..06191994af62 100644 --- a/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java +++ b/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java @@ -136,7 +136,7 @@ public class KeyStoreCryptoOperationChunkedStreamer { // More input is available, but it wasn't included into the previous chunk // because the chunk reached its maximum permitted size. // Shouldn't have happened. - throw new CryptoOperationException("Nothing consumed from max-sized chunk: " + throw new IllegalStateException("Nothing consumed from max-sized chunk: " + chunk.length + " bytes"); } mBuffered = chunk; @@ -148,7 +148,7 @@ public class KeyStoreCryptoOperationChunkedStreamer { mBufferedOffset = opResult.inputConsumed; mBufferedLength = chunk.length - opResult.inputConsumed; } else { - throw new CryptoOperationException("Consumed more than provided: " + throw new IllegalStateException("Consumed more than provided: " + opResult.inputConsumed + ", provided: " + chunk.length); } @@ -160,7 +160,7 @@ public class KeyStoreCryptoOperationChunkedStreamer { try { bufferedOutput.write(opResult.output); } catch (IOException e) { - throw new CryptoOperationException("Failed to buffer output", e); + throw new IllegalStateException("Failed to buffer output", e); } } } else { @@ -173,7 +173,7 @@ public class KeyStoreCryptoOperationChunkedStreamer { try { bufferedOutput.write(opResult.output); } catch (IOException e) { - throw new CryptoOperationException("Failed to buffer output", e); + throw new IllegalStateException("Failed to buffer output", e); } return bufferedOutput.toByteArray(); } @@ -233,10 +233,10 @@ public class KeyStoreCryptoOperationChunkedStreamer { } if (opResult.inputConsumed < chunk.length) { - throw new CryptoOperationException("Keystore failed to consume all input. Provided: " + throw new IllegalStateException("Keystore failed to consume all input. Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed); } else if (opResult.inputConsumed > chunk.length) { - throw new CryptoOperationException("Keystore consumed more input than provided" + throw new IllegalStateException("Keystore consumed more input than provided" + " . Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed); } diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java index a19bbda3b9ec..175369ce91d0 100644 --- a/keystore/java/android/security/KeyStoreHmacSpi.java +++ b/keystore/java/android/security/KeyStoreHmacSpi.java @@ -69,9 +69,10 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp private final int mKeymasterDigest; private final int mMacSizeBytes; - private String mKeyAliasInKeyStore; + // Fields below are populated by engineInit and should be preserved after engineDoFinal. + private KeyStoreSecretKey mKey; - // The fields below are reset by the engineReset operation. + // Fields below are reset when engineDoFinal succeeds. private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer; private IBinder mOperationToken; private Long mOperationHandle; @@ -89,28 +90,49 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp @Override protected void engineInit(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { + resetAll(); + + boolean success = false; + try { + init(key, params); + ensureKeystoreOperationInitialized(); + success = true; + } finally { + if (!success) { + resetAll(); + } + } + } + + private void init(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, + InvalidAlgorithmParameterException { if (key == null) { throw new InvalidKeyException("key == null"); } else if (!(key instanceof KeyStoreSecretKey)) { throw new InvalidKeyException( "Only Android KeyStore secret keys supported. Key: " + key); } + mKey = (KeyStoreSecretKey) key; if (params != null) { throw new InvalidAlgorithmParameterException( "Unsupported algorithm parameters: " + params); } - mKeyAliasInKeyStore = ((KeyStoreSecretKey) key).getAlias(); - if (mKeyAliasInKeyStore == null) { - throw new InvalidKeyException("Key's KeyStore alias not known"); + } + + private void resetAll() { + mKey = null; + IBinder operationToken = mOperationToken; + if (operationToken != null) { + mOperationToken = null; + mKeyStore.abort(operationToken); } - engineReset(); - ensureKeystoreOperationInitialized(); + mOperationHandle = null; + mChunkedStreamer = null; } - @Override - protected void engineReset() { + private void resetWhilePreservingInitState() { IBinder operationToken = mOperationToken; if (operationToken != null) { mOperationToken = null; @@ -120,11 +142,16 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp mChunkedStreamer = null; } - private void ensureKeystoreOperationInitialized() { + @Override + protected void engineReset() { + resetWhilePreservingInitState(); + } + + private void ensureKeystoreOperationInitialized() throws InvalidKeyException { if (mChunkedStreamer != null) { return; } - if (mKeyAliasInKeyStore == null) { + if (mKey == null) { throw new IllegalStateException("Not initialized"); } @@ -132,7 +159,8 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC); keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest); - OperationResult opResult = mKeyStore.begin(mKeyAliasInKeyStore, + OperationResult opResult = mKeyStore.begin( + mKey.getAlias(), KeymasterDefs.KM_PURPOSE_SIGN, true, keymasterArgs, @@ -141,10 +169,10 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp if (opResult == null) { throw new KeyStoreConnectException(); } else if (opResult.resultCode != KeyStore.NO_ERROR) { - throw KeyStore.getCryptoOperationException(opResult.resultCode); + throw KeyStore.getInvalidKeyException(opResult.resultCode); } if (opResult.token == null) { - throw new CryptoOperationException("Keystore returned null operation token"); + throw new IllegalStateException("Keystore returned null operation token"); } mOperationToken = opResult.token; mOperationHandle = opResult.operationHandle; @@ -160,31 +188,39 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp @Override protected void engineUpdate(byte[] input, int offset, int len) { - ensureKeystoreOperationInitialized(); + try { + ensureKeystoreOperationInitialized(); + } catch (InvalidKeyException e) { + throw new IllegalStateException("Failed to reinitialize MAC", e); + } byte[] output; try { output = mChunkedStreamer.update(input, offset, len); } catch (KeyStoreException e) { - throw KeyStore.getCryptoOperationException(e); + throw new IllegalStateException("Keystore operation failed", e); } if ((output != null) && (output.length != 0)) { - throw new CryptoOperationException("Update operation unexpectedly produced output"); + throw new IllegalStateException("Update operation unexpectedly produced output"); } } @Override protected byte[] engineDoFinal() { - ensureKeystoreOperationInitialized(); + try { + ensureKeystoreOperationInitialized(); + } catch (InvalidKeyException e) { + throw new IllegalStateException("Failed to reinitialize MAC", e); + } byte[] result; try { result = mChunkedStreamer.doFinal(null, 0, 0); } catch (KeyStoreException e) { - throw KeyStore.getCryptoOperationException(e); + throw new IllegalStateException("Keystore operation failed", e); } - engineReset(); + resetWhilePreservingInitState(); return result; } diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java index 87e7ee644444..dde3b8fe3771 100644 --- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java @@ -200,7 +200,8 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { int errorCode = mKeyStore.generateKey( keyAliasInKeystore, args, additionalEntropy, flags, new KeyCharacteristics()); if (errorCode != KeyStore.NO_ERROR) { - throw KeyStore.getCryptoOperationException(errorCode); + throw new IllegalStateException( + "Keystore operation failed", KeyStore.getKeyStoreException(errorCode)); } String keyAlgorithmJCA = KeymasterUtils.getJcaSecretKeyAlgorithm(mKeymasterAlgorithm, mKeymasterDigest); diff --git a/keystore/java/android/security/UserNotAuthenticatedException.java b/keystore/java/android/security/UserNotAuthenticatedException.java index e6342ef79673..d0410b8f0171 100644 --- a/keystore/java/android/security/UserNotAuthenticatedException.java +++ b/keystore/java/android/security/UserNotAuthenticatedException.java @@ -16,13 +16,15 @@ package android.security; +import java.security.InvalidKeyException; + /** * Indicates that a cryptographic operation could not be performed because the user has not been * authenticated recently enough. * * @hide */ -public class UserNotAuthenticatedException extends CryptoOperationException { +public class UserNotAuthenticatedException extends InvalidKeyException { /** * Constructs a new {@code UserNotAuthenticatedException} without detail message and cause. diff --git a/keystore/tests/src/android/security/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/AndroidKeyStoreTest.java index 7a88deefa791..a7046dd29cec 100644 --- a/keystore/tests/src/android/security/AndroidKeyStoreTest.java +++ b/keystore/tests/src/android/security/AndroidKeyStoreTest.java @@ -18,7 +18,7 @@ package android.security; import com.android.org.bouncycastle.x509.X509V3CertificateGenerator; -import com.android.org.conscrypt.NativeCrypto; +import com.android.org.conscrypt.NativeConstants; import com.android.org.conscrypt.OpenSSLEngine; import android.test.AndroidTestCase; @@ -768,7 +768,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase { assertAliases(new String[] {}); assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1, - KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, + KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); assertAliases(new String[] { TEST_ALIAS_1 }); @@ -797,7 +797,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase { assertAliases(new String[] {}); assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1, - KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, + KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); assertTrue("Should contain generated private key", mKeyStore.containsAlias(TEST_ALIAS_1)); @@ -1963,7 +1963,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase { { final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1; assertTrue(mAndroidKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, - NativeCrypto.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); + NativeConstants.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); Key key = mKeyStore.getKey(TEST_ALIAS_1, null); @@ -2019,7 +2019,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase { { final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1; assertTrue(mAndroidKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, - NativeCrypto.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); + NativeConstants.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_1, TEST_SERIAL_1, TEST_DN_1, NOW, NOW_PLUS_10_YEARS); @@ -2032,7 +2032,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase { { final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_2; assertTrue(mAndroidKeyStore.generate(privateKeyAlias, KeyStore.UID_SELF, - NativeCrypto.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); + NativeConstants.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_2, TEST_SERIAL_2, TEST_DN_2, NOW, NOW_PLUS_10_YEARS); @@ -2064,7 +2064,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase { { final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1; assertTrue(mAndroidKeyStore.generate(privateKeyAlias, - android.security.KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, 1024, + android.security.KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, 1024, android.security.KeyStore.FLAG_NONE, null)); X509Certificate cert = @@ -2116,7 +2116,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase { assertAliases(new String[] { TEST_ALIAS_1, TEST_ALIAS_2 }); assertTrue(mAndroidKeyStore.generate(Credentials.USER_PRIVATE_KEY + TEST_ALIAS_3, - KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, + KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); assertEquals("The keystore size should match expected", 3, mKeyStore.size()); @@ -2184,7 +2184,7 @@ public class AndroidKeyStoreTest extends AndroidTestCase { private void setupKey() throws Exception { final String privateKeyAlias = Credentials.USER_PRIVATE_KEY + TEST_ALIAS_1; assertTrue(mAndroidKeyStore - .generate(privateKeyAlias, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, 1024, + .generate(privateKeyAlias, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, 1024, KeyStore.FLAG_ENCRYPTED, null)); X509Certificate cert = generateCertificate(mAndroidKeyStore, TEST_ALIAS_1, TEST_SERIAL_1, diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java index 1a5552a18df8..916b1ba9ac46 100644 --- a/keystore/tests/src/android/security/KeyStoreTest.java +++ b/keystore/tests/src/android/security/KeyStoreTest.java @@ -32,7 +32,7 @@ import android.test.ActivityUnitTestCase; import android.test.AssertionFailedError; import android.test.MoreAsserts; import android.test.suitebuilder.annotation.MediumTest; -import com.android.org.conscrypt.NativeCrypto; +import com.android.org.conscrypt.NativeConstants; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Date; @@ -365,7 +365,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { public void testGenerate_NotInitialized_Fail() throws Exception { assertFalse("Should fail when keystore is not initialized", - mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); } @@ -373,7 +373,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { mKeyStore.password(TEST_PASSWD); mKeyStore.lock(); assertFalse("Should fail when keystore is locked", - mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); } @@ -381,7 +381,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { assertTrue(mKeyStore.password(TEST_PASSWD)); assertTrue("Should be able to generate key when unlocked", - mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue(mKeyStore.contains(TEST_KEYNAME)); assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID)); @@ -391,7 +391,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { assertTrue(mKeyStore.password(TEST_PASSWD)); assertTrue("Should be able to generate key when unlocked", - mKeyStore.generate(TEST_KEYNAME, Process.WIFI_UID, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, Process.WIFI_UID, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID)); assertFalse(mKeyStore.contains(TEST_KEYNAME)); @@ -401,7 +401,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { assertTrue(mKeyStore.password(TEST_PASSWD)); assertFalse(mKeyStore.generate(TEST_KEYNAME, Process.BLUETOOTH_UID, - NativeCrypto.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); + NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.BLUETOOTH_UID)); assertFalse(mKeyStore.contains(TEST_KEYNAME, Process.WIFI_UID)); assertFalse(mKeyStore.contains(TEST_KEYNAME)); @@ -447,7 +447,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { public void testSign_Success() throws Exception { mKeyStore.password(TEST_PASSWD); - assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue(mKeyStore.contains(TEST_KEYNAME)); final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA); @@ -458,7 +458,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { public void testVerify_Success() throws Exception { mKeyStore.password(TEST_PASSWD); - assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue(mKeyStore.contains(TEST_KEYNAME)); final byte[] signature = mKeyStore.sign(TEST_KEYNAME, TEST_DATA); @@ -486,7 +486,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { mKeyStore.password(TEST_PASSWD)); assertTrue("Should be able to generate key for testcase", - mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue("Should be able to grant key to other user", @@ -520,7 +520,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { mKeyStore.password(TEST_PASSWD)); assertTrue("Should be able to generate key for testcase", - mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue("Should be able to grant key to other user", @@ -554,7 +554,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { mKeyStore.password(TEST_PASSWD)); assertTrue("Should be able to generate key for testcase", - mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertFalse("Should not be able to revoke not existent grant", @@ -566,7 +566,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { mKeyStore.password(TEST_PASSWD)); assertTrue("Should be able to generate key for testcase", - mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue("Should be able to grant key to other user", @@ -584,7 +584,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { mKeyStore.password(TEST_PASSWD)); assertTrue("Should be able to generate key for testcase", - mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue("Should be able to grant key to other user", @@ -605,7 +605,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { assertFalse(mKeyStore.contains(TEST_KEYNAME)); - assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue(mKeyStore.contains(TEST_KEYNAME)); @@ -644,7 +644,7 @@ public class KeyStoreTest extends ActivityUnitTestCase<Activity> { assertFalse(mKeyStore.contains(TEST_KEYNAME)); - assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeCrypto.EVP_PKEY_RSA, + assertTrue(mKeyStore.generate(TEST_KEYNAME, KeyStore.UID_SELF, NativeConstants.EVP_PKEY_RSA, RSA_KEY_SIZE, KeyStore.FLAG_ENCRYPTED, null)); assertTrue(mKeyStore.contains(TEST_KEYNAME)); diff --git a/libs/androidfw/ObbFile.cpp b/libs/androidfw/ObbFile.cpp index 195fa9ac00d3..95332a35eb7d 100644 --- a/libs/androidfw/ObbFile.cpp +++ b/libs/androidfw/ObbFile.cpp @@ -337,7 +337,9 @@ bool ObbFile::removeFrom(int fd) return false; } - ftruncate(fd, mFooterStart); + if (ftruncate(fd, mFooterStart) == -1) { + return false; + } return true; } diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java index b2886bb473b1..541d871bd657 100644 --- a/media/java/android/media/MediaHTTPConnection.java +++ b/media/java/android/media/MediaHTTPConnection.java @@ -32,6 +32,7 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.NoRouteToHostException; import java.net.ProtocolException; +import java.net.UnknownServiceException; import java.util.HashMap; import java.util.Map; @@ -337,7 +338,10 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub { } catch (NoRouteToHostException e) { Log.w(TAG, "readAt " + offset + " / " + size + " => " + e); return MEDIA_ERROR_UNSUPPORTED; - } catch (IOException e) { + } catch (UnknownServiceException e) { + Log.w(TAG, "readAt " + offset + " / " + size + " => " + e); + return MEDIA_ERROR_UNSUPPORTED; + }catch (IOException e) { if (VERBOSE) { Log.d(TAG, "readAt " + offset + " / " + size + " => -1"); } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 69a4ac02a058..af5025b8d151 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -4120,8 +4120,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public int finishPostLayoutPolicyLw() { - if (mWinShowWhenLocked != null && - mWinShowWhenLocked != mTopFullscreenOpaqueWindowState) { + if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null && + mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken() + && isKeyguardLocked()) { // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the // fullscreen window. // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not. diff --git a/preloaded-classes b/preloaded-classes index 151766f6e249..7a41bb268d80 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -828,6 +828,11 @@ android.hardware.soundtrigger.SoundTriggerModule android.hardware.usb.UsbDevice android.hardware.usb.UsbDeviceConnection android.hardware.usb.UsbRequest +# Initializing android.icu.impl.ICUBinary loads the ICU data. +# Opening the files in the Zygote avoids StrictMode violations. +# It also ensures the ICU data files are mapped on boot and all +# apps will be consistent (even if files are added to /data). +android.icu.impl.ICUBinary android.inputmethodservice.ExtractEditText android.location.Location android.location.Location$1 diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java index 65056ac5c22d..dda468a0de02 100644 --- a/rs/java/android/renderscript/Script.java +++ b/rs/java/android/renderscript/Script.java @@ -66,7 +66,6 @@ public class Script extends BaseObj { } /** - * @hide Pending API review * InvokeID is an identifier for an invoke function. It is used * as an identifier for ScriptGroup creation. * @@ -86,7 +85,6 @@ public class Script extends BaseObj { private final SparseArray<InvokeID> mIIDs = new SparseArray<InvokeID>(); /** - * @hide Pending API review * Only to be used by generated reflected classes. */ protected InvokeID createInvokeID(int slot) { diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java index 51c838f9ef84..be8b0fd77911 100644 --- a/rs/java/android/renderscript/ScriptGroup.java +++ b/rs/java/android/renderscript/ScriptGroup.java @@ -16,32 +16,30 @@ package android.renderscript; +import android.util.Log; +import android.util.Pair; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** - * ScriptGroup creates a group of kernels that are executed - * together with one execution call as if they were a single kernel. - * The kernels may be connected internally or to an external allocation. - * The intermediate results for internal connections are not observable - * after the execution of the script. + * A group of kernels that are executed + * together with one execution call as if they were a single kernel * <p> - * External connections are grouped into inputs and outputs. - * All outputs are produced by a script kernel and placed into a - * user-supplied allocation. Inputs provide the input of a kernel. - * Inputs bound to script globals are set directly upon the script. + * In addition to kernels, a script group may contain invocable functions as well. + * A script group may take inputs and generate outputs, which are consumed and + * produced by its member kernels. + * Inside a script group, outputs from one kernel can be passed to another kernel as inputs. + * The API disallows cyclic dependencies among kernels in a script group, + * effectively making it a directed acyclic graph (DAG) of kernels. * <p> - * A ScriptGroup must contain at least one kernel. A ScriptGroup - * must contain only a single directed acyclic graph (DAG) of - * script kernels and connections. Attempting to create a - * ScriptGroup with multiple DAGs or attempting to create - * a cycle within a ScriptGroup will throw an exception. - * <p> - * Currently, all kernels in a ScriptGroup must be from separate - * Script objects. Attempting to use multiple kernels from the same - * Script object will result in an {@link android.renderscript.RSInvalidStateException}. - * + * Grouping kernels together allows for more efficient execution. For example, + * runtime and compiler optimization can be applied to reduce computation and + * communication overhead, and to make better use of the CPU and the GPU. **/ public final class ScriptGroup extends BaseObj { + private static final String TAG = "ScriptGroup"; IO mOutputs[]; IO mInputs[]; @@ -88,15 +86,364 @@ public final class ScriptGroup extends BaseObj { } + /** + * An opaque class for closures + * <p> + * A closure represents a function call to a kernel or invocable function, + * combined with arguments and values for global variables. A closure is + * created using the {@link android.renderscript.ScriptGroup.Builder2#addKernel} or + * {@link android.renderscript.ScriptGroup.Builder2#addInvoke} + * method. + */ + + public static final class Closure extends BaseObj { + private Object[] mArgs; + private Allocation mReturnValue; + private Map<Script.FieldID, Object> mBindings; + + private Future mReturnFuture; + private Map<Script.FieldID, Future> mGlobalFuture; + + private FieldPacker mFP; + + private static final String TAG = "Closure"; + + Closure(long id, RenderScript rs) { + super(id, rs); + } + + Closure(RenderScript rs, Script.KernelID kernelID, Type returnType, + Object[] args, Map<Script.FieldID, Object> globals) { + super(0, rs); + + mArgs = args; + mReturnValue = Allocation.createTyped(rs, returnType); + mBindings = globals; + mGlobalFuture = new HashMap<Script.FieldID, Future>(); + + int numValues = args.length + globals.size(); + + long[] fieldIDs = new long[numValues]; + long[] values = new long[numValues]; + int[] sizes = new int[numValues]; + long[] depClosures = new long[numValues]; + long[] depFieldIDs = new long[numValues]; + + int i; + for (i = 0; i < args.length; i++) { + Object obj = args[i]; + fieldIDs[i] = 0; + if (obj instanceof Input) { + Input unbound = (Input)obj; + unbound.addReference(this, i); + } else { + retrieveValueAndDependenceInfo(rs, i, args[i], values, sizes, + depClosures, depFieldIDs); + } + } + + for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) { + Object obj = entry.getValue(); + Script.FieldID fieldID = entry.getKey(); + fieldIDs[i] = fieldID.getID(rs); + if (obj instanceof Input) { + Input unbound = (Input)obj; + unbound.addReference(this, fieldID); + } else { + retrieveValueAndDependenceInfo(rs, i, obj, values, + sizes, depClosures, depFieldIDs); + } + i++; + } + + long id = rs.nClosureCreate(kernelID.getID(rs), mReturnValue.getID(rs), + fieldIDs, values, sizes, depClosures, depFieldIDs); + + setID(id); + } + + Closure(RenderScript rs, Script.InvokeID invokeID, + Object[] args, Map<Script.FieldID, Object> globals) { + super(0, rs); + mFP = FieldPacker.createFromArray(args); + + mArgs = args; + mBindings = globals; + mGlobalFuture = new HashMap<Script.FieldID, Future>(); + + int numValues = globals.size(); + + long[] fieldIDs = new long[numValues]; + long[] values = new long[numValues]; + int[] sizes = new int[numValues]; + long[] depClosures = new long[numValues]; + long[] depFieldIDs = new long[numValues]; + + int i = 0; + for (Map.Entry<Script.FieldID, Object> entry : globals.entrySet()) { + Object obj = entry.getValue(); + Script.FieldID fieldID = entry.getKey(); + fieldIDs[i] = fieldID.getID(rs); + if (obj instanceof Input) { + Input unbound = (Input)obj; + unbound.addReference(this, fieldID); + } else { + retrieveValueAndDependenceInfo(rs, i, obj, values, + sizes, depClosures, depFieldIDs); + } + i++; + } + + long id = rs.nInvokeClosureCreate(invokeID.getID(rs), mFP.getData(), fieldIDs, + values, sizes); + + setID(id); + } + + private static + void retrieveValueAndDependenceInfo(RenderScript rs, + int index, Object obj, + long[] values, int[] sizes, + long[] depClosures, + long[] depFieldIDs) { + + if (obj instanceof Future) { + Future f = (Future)obj; + obj = f.getValue(); + depClosures[index] = f.getClosure().getID(rs); + Script.FieldID fieldID = f.getFieldID(); + depFieldIDs[index] = fieldID != null ? fieldID.getID(rs) : 0; + if (obj == null) { + // Value is originally created by the owner closure + values[index] = 0; + sizes[index] = 0; + return; + } + } else { + depClosures[index] = 0; + depFieldIDs[index] = 0; + } + + ValueAndSize vs = new ValueAndSize(rs, obj); + values[index] = vs.value; + sizes[index] = vs.size; + } + + /** + * Returns the future for the return value + * + * @return a future + */ + + public Future getReturn() { + if (mReturnFuture == null) { + mReturnFuture = new Future(this, null, mReturnValue); + } + + return mReturnFuture; + } + + /** + * Returns the future for a global variable + * + * @param field the field ID for the global variable + * @return a future + */ + + public Future getGlobal(Script.FieldID field) { + Future f = mGlobalFuture.get(field); + + if (f == null) { + // If the field is not bound to this closure, this will return a future + // without an associated value (reference). So this is not working for + // cross-module (cross-script) linking in this case where a field not + // explicitly bound. + f = new Future(this, field, mBindings.get(field)); + mGlobalFuture.put(field, f); + } + + return f; + } + + void setArg(int index, Object obj) { + mArgs[index] = obj; + ValueAndSize vs = new ValueAndSize(mRS, obj); + mRS.nClosureSetArg(getID(mRS), index, vs.value, vs.size); + } + + void setGlobal(Script.FieldID fieldID, Object obj) { + mBindings.put(fieldID, obj); + ValueAndSize vs = new ValueAndSize(mRS, obj); + mRS.nClosureSetGlobal(getID(mRS), fieldID.getID(mRS), vs.value, vs.size); + } + + private static final class ValueAndSize { + public ValueAndSize(RenderScript rs, Object obj) { + if (obj instanceof Allocation) { + value = ((Allocation)obj).getID(rs); + size = -1; + } else if (obj instanceof Boolean) { + value = ((Boolean)obj).booleanValue() ? 1 : 0; + size = 4; + } else if (obj instanceof Integer) { + value = ((Integer)obj).longValue(); + size = 4; + } else if (obj instanceof Long) { + value = ((Long)obj).longValue(); + size = 8; + } else if (obj instanceof Float) { + value = ((Float)obj).longValue(); + size = 4; + } else if (obj instanceof Double) { + value = ((Double)obj).longValue(); + size = 8; + } + } + public long value; + public int size; + } + } + + /** + * An opaque class for futures + * <p> + * A future represents an output of a closure, either the return value of + * the function, or the value of a global variable written by the function. + * A future is created by calling the {@link Closure#getReturn} or + * {@link Closure#getGlobal} method. + */ + + public static final class Future { + Closure mClosure; + Script.FieldID mFieldID; + Object mValue; + + Future(Closure closure, Script.FieldID fieldID, Object value) { + mClosure = closure; + mFieldID = fieldID; + mValue = value; + } + + Closure getClosure() { return mClosure; } + Script.FieldID getFieldID() { return mFieldID; } + Object getValue() { return mValue; } + } + + /** + * An opaque class for script group inputs + * <p> + * Created by calling the {@link Builder2#addInput} method. The value + * is assigned in {@link ScriptGroup#execute(Object...)} method as + * one of its arguments. Arguments to the execute method should be in + * the same order as intputs are added using the addInput method. + */ + + public static final class Input { + // Either mFieldID or mArgIndex should be set but not both. + List<Pair<Closure, Script.FieldID>> mFieldID; + // -1 means unset. Legal values are 0 .. n-1, where n is the number of + // arguments for the referencing closure. + List<Pair<Closure, Integer>> mArgIndex; + + Input() { + mFieldID = new ArrayList<Pair<Closure, Script.FieldID>>(); + mArgIndex = new ArrayList<Pair<Closure, Integer>>(); + } + + void addReference(Closure closure, int index) { + mArgIndex.add(Pair.create(closure, Integer.valueOf(index))); + } + + void addReference(Closure closure, Script.FieldID fieldID) { + mFieldID.add(Pair.create(closure, fieldID)); + } + + void set(Object value) { + for (Pair<Closure, Integer> p : mArgIndex) { + Closure closure = p.first; + int index = p.second.intValue(); + closure.setArg(index, value); + } + for (Pair<Closure, Script.FieldID> p : mFieldID) { + Closure closure = p.first; + Script.FieldID fieldID = p.second; + closure.setGlobal(fieldID, value); + } + } + } + + private String mName; + private List<Closure> mClosures; + private List<Input> mInputs2; + private Future[] mOutputs2; + ScriptGroup(long id, RenderScript rs) { super(id, rs); } + ScriptGroup(RenderScript rs, String name, List<Closure> closures, + List<Input> inputs, Future[] outputs) { + super(0, rs); + mName = name; + mClosures = closures; + mInputs2 = inputs; + mOutputs2 = outputs; + + long[] closureIDs = new long[closures.size()]; + for (int i = 0; i < closureIDs.length; i++) { + closureIDs[i] = closures.get(i).getID(rs); + } + long id = rs.nScriptGroup2Create(name, ScriptC.mCachePath, closureIDs); + setID(id); + } + + /** + * Executes a script group + * + * @param inputs inputs to the script group + * @return outputs of the script group as an array of objects + */ + + public Object[] execute(Object... inputs) { + if (inputs.length < mInputs2.size()) { + Log.e(TAG, this.toString() + " receives " + inputs.length + " inputs, " + + "less than expected " + mInputs2.size()); + return null; + } + + if (inputs.length > mInputs2.size()) { + Log.i(TAG, this.toString() + " receives " + inputs.length + " inputs, " + + "more than expected " + mInputs2.size()); + } + + for (int i = 0; i < mInputs2.size(); i++) { + Object obj = inputs[i]; + if (obj instanceof Future || obj instanceof Input) { + Log.e(TAG, this.toString() + ": input " + i + + " is a future or unbound value"); + return null; + } + Input unbound = mInputs2.get(i); + unbound.set(obj); + } + + mRS.nScriptGroup2Execute(getID(mRS)); + + Object[] outputObjs = new Object[mOutputs2.length]; + int i = 0; + for (Future f : mOutputs2) { + outputObjs[i++] = f.getValue(); + } + return outputObjs; + } + /** * Sets an input of the ScriptGroup. This specifies an * Allocation to be used for kernels that require an input * Allocation provided from outside of the ScriptGroup. * + * @deprecated Set arguments to {@link #execute(Object...)} instead. + * * @param s The ID of the kernel where the allocation should be * connected. * @param a The allocation to connect. @@ -117,6 +464,8 @@ public final class ScriptGroup extends BaseObj { * Allocation to be used for the kernels that require an output * Allocation visible after the ScriptGroup is executed. * + * @deprecated Use return value of {@link #execute(Object...)} instead. + * * @param s The ID of the kernel where the allocation should be * connected. * @param a The allocation to connect. @@ -136,6 +485,9 @@ public final class ScriptGroup extends BaseObj { * Execute the ScriptGroup. This will run all the kernels in * the ScriptGroup. No internal connection results will be visible * after execution of the ScriptGroup. + * + * @deprecated Use {@link #execute} instead. + * */ public void execute() { mRS.nScriptGroupExecute(getID(mRS)); @@ -164,6 +516,8 @@ public final class ScriptGroup extends BaseObj { * Once all connections are made, a call to {@link #create} will * return the ScriptGroup object. * + * @deprecated Use {@link Builder2} instead. + * */ public static final class Builder { private RenderScript mRS; @@ -464,7 +818,210 @@ public final class ScriptGroup extends BaseObj { } + /** + * Represents a binding of a value to a global variable in a + * kernel or invocable function. Used in closure creation. + */ -} + public static final class Binding { + private final Script.FieldID mField; + private final Object mValue; + + /** + * Returns a Binding object that binds value to field + * + * @param field the Script.FieldID of the global variable + * @param value the value + */ + + public Binding(Script.FieldID field, Object value) { + mField = field; + mValue = value; + } + + /** + * Returns the field ID + */ + + public Script.FieldID getField() { return mField; } + + /** + * Returns the value + */ + + public Object getValue() { return mValue; } + } + + /** + * The builder class for creating script groups + * <p> + * A script group is created using closures (see class {@link Closure}). + * A closure is a function call to a kernel or + * invocable function. Each function argument or global variable accessed inside + * the function is bound to 1) a known value, 2) a script group input + * (see class {@link Input}), or 3) a + * future (see class {@link Future}). + * A future is the output of a closure, either the return value of the + * function or a global variable written by that function. + * <p> + * Closures are created using the {@link #addKernel} or {@link #addInvoke} + * methods. + * When a closure is created, futures from previously created closures + * can be used as its inputs. + * External script group inputs can be used as inputs to individual closures as well. + * An external script group input is created using the {@link #addInput} method. + * A script group is created by a call to the {@link #create} method, which + * accepts an array of futures as the outputs for the script group. + * <p> + * Closures in a script group can be evaluated in any order as long as the + * following conditions are met: + * 1) a closure must be evaluated before any other closures that take its + * futures as inputs; + * 2) all closures added before an invoke closure must be evaluated + * before it; + * and 3) all closures added after an invoke closure must be evaluated after + * it. + * As a special case, the order that the closures are added is a legal + * evaluation order. However, other evaluation orders are possible, including + * concurrently evaluating independent closures. + */ + + public static final class Builder2 { + RenderScript mRS; + List<Closure> mClosures; + List<Input> mInputs; + private static final String TAG = "ScriptGroup.Builder2"; + + /** + * Returns a Builder object + * + * @param rs the RenderScript context + */ + public Builder2(RenderScript rs) { + mRS = rs; + mClosures = new ArrayList<Closure>(); + mInputs = new ArrayList<Input>(); + } + /** + * Adds a closure for a kernel + * + * @param k Kernel ID for the kernel function + * @param returnType Allocation type for the return value + * @param args arguments to the kernel function + * @param globalBindings bindings for global variables + * @return a closure + */ + private Closure addKernelInternal(Script.KernelID k, Type returnType, Object[] args, + Map<Script.FieldID, Object> globalBindings) { + Closure c = new Closure(mRS, k, returnType, args, globalBindings); + mClosures.add(c); + return c; + } + + /** + * Adds a closure for an invocable function + * + * @param invoke Invoke ID for the invocable function + * @param args arguments to the invocable function + * @param globalBindings bindings for global variables + * @return a closure + */ + + private Closure addInvokeInternal(Script.InvokeID invoke, Object[] args, + Map<Script.FieldID, Object> globalBindings) { + Closure c = new Closure(mRS, invoke, args, globalBindings); + mClosures.add(c); + return c; + } + + /** + * Adds a script group input + * + * @return a script group input, which can be used as an argument or a value to + * a global variable for creating closures + */ + public Input addInput() { + Input unbound = new Input(); + mInputs.add(unbound); + return unbound; + } + + /** + * Adds a closure for a kernel + * + * @param k Kernel ID for the kernel function + * @param argsAndBindings arguments followed by bindings for global variables + * @return a closure + */ + + public Closure addKernel(Script.KernelID k, Type returnType, Object... argsAndBindings) { + ArrayList<Object> args = new ArrayList<Object>(); + Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>(); + if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) { + return null; + } + return addKernelInternal(k, returnType, args.toArray(), bindingMap); + } + + /** + * Adds a closure for an invocable function + * + * @param invoke Invoke ID for the invocable function + * @param argsAndBindings arguments followed by bindings for global variables + * @return a closure + */ + + public Closure addInvoke(Script.InvokeID invoke, Object... argsAndBindings) { + ArrayList<Object> args = new ArrayList<Object>(); + Map<Script.FieldID, Object> bindingMap = new HashMap<Script.FieldID, Object>(); + if (!seperateArgsAndBindings(argsAndBindings, args, bindingMap)) { + return null; + } + return addInvokeInternal(invoke, args.toArray(), bindingMap); + } + + /** + * Creates a script group + * + * @param name name for the script group. Legal names can only contain letters, digits, + * '-', or '_'. The name can be no longer than 100 characters. + * @param outputs futures intended as outputs of the script group + * @return a script group + */ + + public ScriptGroup create(String name, Future... outputs) { + if (name == null || name.isEmpty() || name.length() > 100 || + !name.equals(name.replaceAll("[^a-zA-Z0-9-]", "_"))) { + throw new RSIllegalArgumentException("invalid script group name"); + } + ScriptGroup ret = new ScriptGroup(mRS, name, mClosures, mInputs, outputs); + return ret; + } + + private boolean seperateArgsAndBindings(Object[] argsAndBindings, + ArrayList<Object> args, + Map<Script.FieldID, Object> bindingMap) { + int i; + for (i = 0; i < argsAndBindings.length; i++) { + if (argsAndBindings[i] instanceof Binding) { + break; + } + args.add(argsAndBindings[i]); + } + + for (; i < argsAndBindings.length; i++) { + if (!(argsAndBindings[i] instanceof Binding)) { + return false; + } + Binding b = (Binding)argsAndBindings[i]; + bindingMap.put(b.getField(), b.getValue()); + } + + return true; + } + + } + +} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 05a4d7e1943d..95a08677bf06 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1287,10 +1287,11 @@ public final class ActivityManagerService extends ActivityManagerNative final ServiceThread mHandlerThread; final MainHandler mHandler; + final UiHandler mUiHandler; - final class MainHandler extends Handler { - public MainHandler(Looper looper) { - super(looper, null, true); + final class UiHandler extends Handler { + public UiHandler() { + super(com.android.server.UiThread.get().getLooper(), null, true); } @Override @@ -1403,15 +1404,6 @@ public final class ActivityManagerService extends ActivityManagerNative d.show(); ensureBootCompleted(); } break; - case UPDATE_CONFIGURATION_MSG: { - final ContentResolver resolver = mContext.getContentResolver(); - Settings.System.putConfiguration(resolver, (Configuration)msg.obj); - } break; - case GC_BACKGROUND_PROCESSES_MSG: { - synchronized (ActivityManagerService.this) { - performAppGcsIfAppropriateLocked(); - } - } break; case WAIT_FOR_DEBUGGER_MSG: { synchronized (ActivityManagerService.this) { ProcessRecord app = (ProcessRecord)msg.obj; @@ -1432,6 +1424,88 @@ public final class ActivityManagerService extends ActivityManagerNative } } } break; + case SHOW_UID_ERROR_MSG: { + if (mShowDialogs) { + AlertDialog d = new BaseErrorDialog(mContext); + d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + d.setCancelable(false); + d.setTitle(mContext.getText(R.string.android_system_label)); + d.setMessage(mContext.getText(R.string.system_error_wipe_data)); + d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), + obtainMessage(DISMISS_DIALOG_MSG, d)); + d.show(); + } + } break; + case SHOW_FINGERPRINT_ERROR_MSG: { + if (mShowDialogs) { + AlertDialog d = new BaseErrorDialog(mContext); + d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + d.setCancelable(false); + d.setTitle(mContext.getText(R.string.android_system_label)); + d.setMessage(mContext.getText(R.string.system_error_manufacturer)); + d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), + obtainMessage(DISMISS_DIALOG_MSG, d)); + d.show(); + } + } break; + case SHOW_COMPAT_MODE_DIALOG_MSG: { + synchronized (ActivityManagerService.this) { + ActivityRecord ar = (ActivityRecord) msg.obj; + if (mCompatModeDialog != null) { + if (mCompatModeDialog.mAppInfo.packageName.equals( + ar.info.applicationInfo.packageName)) { + return; + } + mCompatModeDialog.dismiss(); + mCompatModeDialog = null; + } + if (ar != null && false) { + if (mCompatModePackages.getPackageAskCompatModeLocked( + ar.packageName)) { + int mode = mCompatModePackages.computeCompatModeLocked( + ar.info.applicationInfo); + if (mode == ActivityManager.COMPAT_MODE_DISABLED + || mode == ActivityManager.COMPAT_MODE_ENABLED) { + mCompatModeDialog = new CompatModeDialog( + ActivityManagerService.this, mContext, + ar.info.applicationInfo); + mCompatModeDialog.show(); + } + } + } + } + break; + } + case START_USER_SWITCH_MSG: { + showUserSwitchDialog(msg.arg1, (String) msg.obj); + break; + } + case DISMISS_DIALOG_MSG: { + final Dialog d = (Dialog) msg.obj; + d.dismiss(); + break; + } + } + } + } + + final class MainHandler extends Handler { + public MainHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case UPDATE_CONFIGURATION_MSG: { + final ContentResolver resolver = mContext.getContentResolver(); + Settings.System.putConfiguration(resolver, (Configuration) msg.obj); + } break; + case GC_BACKGROUND_PROCESSES_MSG: { + synchronized (ActivityManagerService.this) { + performAppGcsIfAppropriateLocked(); + } + } break; case SERVICE_TIMEOUT_MSG: { if (mDidDexOpt) { mDidDexOpt = false; @@ -1496,30 +1570,6 @@ public final class ActivityManagerService extends ActivityManagerNative } } } break; - case SHOW_UID_ERROR_MSG: { - if (mShowDialogs) { - AlertDialog d = new BaseErrorDialog(mContext); - d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); - d.setCancelable(false); - d.setTitle(mContext.getText(R.string.android_system_label)); - d.setMessage(mContext.getText(R.string.system_error_wipe_data)); - d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), - mHandler.obtainMessage(DISMISS_DIALOG_MSG, d)); - d.show(); - } - } break; - case SHOW_FINGERPRINT_ERROR_MSG: { - if (mShowDialogs) { - AlertDialog d = new BaseErrorDialog(mContext); - d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); - d.setCancelable(false); - d.setTitle(mContext.getText(R.string.android_system_label)); - d.setMessage(mContext.getText(R.string.system_error_manufacturer)); - d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), - mHandler.obtainMessage(DISMISS_DIALOG_MSG, d)); - d.show(); - } - } break; case PROC_START_TIMEOUT_MSG: { if (mDidDexOpt) { mDidDexOpt = false; @@ -1620,34 +1670,6 @@ public final class ActivityManagerService extends ActivityManagerNative sendMessageDelayed(nmsg, POWER_CHECK_DELAY); } } break; - case SHOW_COMPAT_MODE_DIALOG_MSG: { - synchronized (ActivityManagerService.this) { - ActivityRecord ar = (ActivityRecord)msg.obj; - if (mCompatModeDialog != null) { - if (mCompatModeDialog.mAppInfo.packageName.equals( - ar.info.applicationInfo.packageName)) { - return; - } - mCompatModeDialog.dismiss(); - mCompatModeDialog = null; - } - if (ar != null && false) { - if (mCompatModePackages.getPackageAskCompatModeLocked( - ar.packageName)) { - int mode = mCompatModePackages.computeCompatModeLocked( - ar.info.applicationInfo); - if (mode == ActivityManager.COMPAT_MODE_DISABLED - || mode == ActivityManager.COMPAT_MODE_ENABLED) { - mCompatModeDialog = new CompatModeDialog( - ActivityManagerService.this, mContext, - ar.info.applicationInfo); - mCompatModeDialog.show(); - } - } - } - } - break; - } case DISPATCH_PROCESSES_CHANGED: { dispatchProcessesChanged(); break; @@ -1668,10 +1690,6 @@ public final class ActivityManagerService extends ActivityManagerNative thread.start(); break; } - case START_USER_SWITCH_MSG: { - showUserSwitchDialog(msg.arg1, (String) msg.obj); - break; - } case REPORT_USER_SWITCH_MSG: { dispatchUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); break; @@ -1779,11 +1797,6 @@ public final class ActivityManagerService extends ActivityManagerNative } break; } - case DISMISS_DIALOG_MSG: { - final Dialog d = (Dialog) msg.obj; - d.dismiss(); - break; - } case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG: { synchronized (ActivityManagerService.this) { int i = mTaskStackListeners.beginBroadcast(); @@ -2078,6 +2091,7 @@ public final class ActivityManagerService extends ActivityManagerNative android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); mHandlerThread.start(); mHandler = new MainHandler(mHandlerThread.getLooper()); + mUiHandler = new UiHandler(); mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", BROADCAST_FG_TIMEOUT, false); @@ -2443,7 +2457,7 @@ public final class ActivityManagerService extends ActivityManagerNative Message msg = Message.obtain(); msg.what = SHOW_COMPAT_MODE_DIALOG_MSG; msg.obj = r.task.askedCompatMode ? null : r; - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); } private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index, @@ -3002,6 +3016,10 @@ public final class ActivityManagerService extends ActivityManagerNative debugFlags |= Zygote.DEBUG_ENABLE_JIT; } } + String genCFIDebugProperty = SystemProperties.get("debug.gencfi"); + if ("true".equals(genCFIDebugProperty)) { + debugFlags |= Zygote.DEBUG_GENERATE_CFI; + } if ("1".equals(SystemProperties.get("debug.jni.logging"))) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } @@ -5100,20 +5118,20 @@ public final class ActivityManagerService extends ActivityManagerNative map.put("activity", activity); } - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); } } final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) { if (!mLaunchWarningShown) { mLaunchWarningShown = true; - mHandler.post(new Runnable() { + mUiHandler.post(new Runnable() { @Override public void run() { synchronized (ActivityManagerService.this) { final Dialog d = new LaunchWarningWindow(mContext, cur, next); d.show(); - mHandler.postDelayed(new Runnable() { + mUiHandler.postDelayed(new Runnable() { @Override public void run() { synchronized (ActivityManagerService.this) { @@ -5802,17 +5820,20 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.isolated) { mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid); } - app.kill(reason, true); - handleAppDiedLocked(app, true, allowRestart); - removeLruProcessLocked(app); - + boolean willRestart = false; if (app.persistent && !app.isolated) { if (!callerWillRestart) { - addAppLocked(app.info, false, null /* ABI override */); + willRestart = true; } else { needRestart = true; } } + app.kill(reason, true); + handleAppDiedLocked(app, willRestart, allowRestart); + if (willRestart) { + removeLruProcessLocked(app); + addAppLocked(app.info, false, null /* ABI override */); + } } else { mRemovedProcesses.add(app); } @@ -8053,7 +8074,7 @@ public final class ActivityManagerService extends ActivityManagerNative msg.what = WAIT_FOR_DEBUGGER_MSG; msg.obj = app; msg.arg1 = waiting ? 1 : 0; - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); } } @@ -11359,7 +11380,7 @@ public final class ActivityManagerService extends ActivityManagerNative Message msg = Message.obtain(); msg.what = SHOW_FACTORY_ERROR_MSG; msg.getData().putCharSequence("msg", errorMsg); - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); } } } @@ -11409,14 +11430,14 @@ public final class ActivityManagerService extends ActivityManagerNative if (AppGlobals.getPackageManager().hasSystemUidErrors()) { Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your" + " data partition or your device will be unstable."); - mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget(); + mUiHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget(); } } catch (RemoteException e) { } if (!Build.isFingerprintConsistent()) { Slog.e(TAG, "Build fingerprint is not consistent, warning user"); - mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget(); + mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget(); } long ident = Binder.clearCallingIdentity(); @@ -11702,7 +11723,7 @@ public final class ActivityManagerService extends ActivityManagerNative data.put("violationMask", violationMask); data.put("info", info); msg.obj = data; - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); Binder.restoreCallingIdentity(origId); } @@ -12157,7 +12178,7 @@ public final class ActivityManagerService extends ActivityManagerNative data.put("result", result); data.put("app", r); msg.obj = data; - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); Binder.restoreCallingIdentity(origId); } @@ -14891,7 +14912,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - for (int i=0; i<cpr.connections.size(); i++) { + for (int i = cpr.connections.size() - 1; i >= 0; i--) { ContentProviderConnection conn = cpr.connections.get(i); if (conn.waiting) { // If this connection is waiting for the provider, then we don't @@ -14983,10 +15004,11 @@ public final class ActivityManagerService extends ActivityManagerNative boolean restart = false; // Remove published content providers. - for (int i=app.pubProviders.size()-1; i>=0; i--) { + for (int i = app.pubProviders.size() - 1; i >= 0; i--) { ContentProviderRecord cpr = app.pubProviders.valueAt(i); final boolean always = app.bad || !allowRestart; - if (removeDyingProviderLocked(app, cpr, always) || always) { + boolean inLaunching = removeDyingProviderLocked(app, cpr, always); + if ((inLaunching || always) && !cpr.connections.isEmpty()) { // We left the provider in the launching list, need to // restart it. restart = true; @@ -15004,7 +15026,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Unregister from connected content providers. if (!app.conProviders.isEmpty()) { - for (int i=0; i<app.conProviders.size(); i++) { + for (int i = app.conProviders.size() - 1; i >= 0; i--) { ContentProviderConnection conn = app.conProviders.get(i); conn.provider.connections.remove(conn); stopAssociationLocked(app.uid, app.processName, conn.provider.uid, @@ -15019,9 +15041,8 @@ public final class ActivityManagerService extends ActivityManagerNative // XXX Commented out for now. Trying to figure out a way to reproduce // the actual situation to identify what is actually going on. if (false) { - for (int i=0; i<mLaunchingProviders.size(); i++) { - ContentProviderRecord cpr = (ContentProviderRecord) - mLaunchingProviders.get(i); + for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) { + ContentProviderRecord cpr = mLaunchingProviders.get(i); if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) { synchronized (cpr) { cpr.launchingApp = null; @@ -15034,7 +15055,7 @@ public final class ActivityManagerService extends ActivityManagerNative skipCurrentReceiverLocked(app); // Unregister any receivers. - for (int i=app.receivers.size()-1; i>=0; i--) { + for (int i = app.receivers.size() - 1; i >= 0; i--) { removeReceiverLocked(app.receivers.valueAt(i)); } app.receivers.clear(); @@ -15052,7 +15073,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - for (int i = mPendingProcessChanges.size()-1; i>=0; i--) { + for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) { ProcessChangeItem item = mPendingProcessChanges.get(i); if (item.pid == app.pid) { mPendingProcessChanges.remove(i); @@ -15127,18 +15148,14 @@ public final class ActivityManagerService extends ActivityManagerNative // and if any run in this process then either schedule a restart of // the process or kill the client waiting for it if this process has // gone bad. - int NL = mLaunchingProviders.size(); boolean restart = false; - for (int i=0; i<NL; i++) { + for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) { ContentProviderRecord cpr = mLaunchingProviders.get(i); if (cpr.launchingApp == app) { - if (!alwaysBad && !app.bad) { + if (!alwaysBad && !app.bad && !cpr.connections.isEmpty()) { restart = true; } else { removeDyingProviderLocked(app, cpr, true); - // cpr should have been removed from mLaunchingProviders - NL = mLaunchingProviders.size(); - i--; } } } @@ -18922,8 +18939,8 @@ public final class ActivityManagerService extends ActivityManagerNative userName = userInfo.name; mTargetUserId = userId; } - mHandler.removeMessages(START_USER_SWITCH_MSG); - mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); + mUiHandler.removeMessages(START_USER_SWITCH_MSG); + mUiHandler.sendMessage(mUiHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); return true; } diff --git a/tools/obbtool/pbkdf2gen.cpp b/tools/obbtool/pbkdf2gen.cpp index 98d67c0b575c..f1d8d04ea01e 100644 --- a/tools/obbtool/pbkdf2gen.cpp +++ b/tools/obbtool/pbkdf2gen.cpp @@ -20,6 +20,7 @@ #include <errno.h> #include <fcntl.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> |