am 2787cab7: am 50ea9422: am 4e7500e1: am c1609dc0: docs: Update information on delivering message to clarify that MessageAPI is not reliable.

* commit '2787cab72b5a4a90a4f443311f08994e2eadbdac':
  docs: Update information on delivering message to clarify that MessageAPI is not reliable.
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index f305b2a..4a8dfbc 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1657,7 +1657,7 @@
     /**
      * 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 5e9b8c1..74699fd 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -211,8 +211,9 @@
                     } 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 @@
                         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 355ec8c..009649f 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -634,6 +634,9 @@
             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/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 10e4db3..5953a98 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -618,7 +618,15 @@
                 // remove based on both its position as well as it's current memory usage, as well
                 // as whether it was directly requested vs. whether it was preloaded by our caching
                 // mechanism.
-                mIndexRemoteViews.remove(getFarthestPositionFrom(pruneFromPosition, visibleWindow));
+                int trimIndex = getFarthestPositionFrom(pruneFromPosition, visibleWindow);
+
+                // Need to check that this is a valid index, to cover the case where you have only
+                // a single view in the cache, but it's larger than the max memory limit
+                if (trimIndex < 0) {
+                    break;
+                }
+
+                mIndexRemoteViews.remove(trimIndex);
             }
 
             // Update the metadata cache
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 75b6446..1e7ee5a 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -40,6 +40,8 @@
     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. */
     public static final int MOUNT_EXTERNAL_NONE = 0;
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 9106ccd..969d236 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -321,7 +321,7 @@
 
         /**
          * 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;
 
@@ -433,6 +433,8 @@
                     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/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 88f0697..7c2b28d 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -875,6 +875,19 @@
     parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf,
                        "-Xzygote-max-boot-retry=");
 
+    /*
+     * 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/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index cfbedda..fb82075 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -200,10 +200,8 @@
          * that can be made while an exception is pending, so we want to
          * get the VM ptr, throw the exception, and then detach the thread.
          */
-        JavaVM* vm = jnienv_to_javavm(env);
         env->Throw(excep);
-        vm->DetachCurrentThread();
-        sleep(60);
+        env->ExceptionDescribe();
         ALOGE("Forcefully exiting");
         exit(1);
     }
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 8c49ff0..5d863c2 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -53,6 +53,14 @@
     public static final int UNDEFINED_ACTION = 9;
     public static final int WRONG_PASSWORD = 10;
 
+    /**
+     * Per operation authentication is needed before this operation is valid.
+     * This is returned from {@link #begin} when begin succeeds but the operation uses
+     * per-operation authentication and must authenticate before calling {@link #update} or
+     * {@link #finish}.
+     */
+    public static final int OP_AUTH_NEEDED = 15;
+
     // Used for UID field to indicate the calling UID.
     public static final int UID_SELF = -1;
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index eeac69a..6eaf812 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -57,7 +57,8 @@
  */
 public class AudioManager {
 
-    private final Context mApplicationContext;
+    private Context mOriginalContext;
+    private Context mApplicationContext;
     private long mVolumeKeyUpTime;
     private final boolean mUseVolumeKeySounds;
     private final boolean mUseFixedVolume;
@@ -621,14 +622,33 @@
      * @hide
      */
     public AudioManager(Context context) {
-        mApplicationContext = context;
-        mUseVolumeKeySounds = mApplicationContext.getResources().getBoolean(
+        setContext(context);
+        mUseVolumeKeySounds = getContext().getResources().getBoolean(
                 com.android.internal.R.bool.config_useVolumeKeySounds);
-        mUseFixedVolume = mApplicationContext.getResources().getBoolean(
+        mUseFixedVolume = getContext().getResources().getBoolean(
                 com.android.internal.R.bool.config_useFixedVolume);
         sAudioPortEventHandler.init();
     }
 
+    private Context getContext() {
+        if (mApplicationContext == null) {
+            setContext(mOriginalContext);
+        }
+        if (mApplicationContext != null) {
+            return mApplicationContext;
+        }
+        return mOriginalContext;
+    }
+
+    private void setContext(Context context) {
+        mApplicationContext = context.getApplicationContext();
+        if (mApplicationContext != null) {
+            mOriginalContext = null;
+        } else {
+            mOriginalContext = context;
+        }
+    }
+
     private static IAudioService getService()
     {
         if (sService != null) {
@@ -663,7 +683,7 @@
      *     or {@link KeyEvent#KEYCODE_MEDIA_AUDIO_TRACK}.
      */
     public void dispatchMediaKeyEvent(KeyEvent keyEvent) {
-        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
+        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
         helper.sendMediaButtonEvent(keyEvent, false);
     }
 
@@ -709,7 +729,7 @@
                 break;
             case KeyEvent.KEYCODE_VOLUME_MUTE:
                 if (event.getRepeatCount() == 0) {
-                    MediaSessionLegacyHelper.getHelper(mApplicationContext)
+                    MediaSessionLegacyHelper.getHelper(getContext())
                             .sendVolumeKeyEvent(event, false);
                 }
                 break;
@@ -737,7 +757,7 @@
                 mVolumeKeyUpTime = SystemClock.uptimeMillis();
                 break;
             case KeyEvent.KEYCODE_VOLUME_MUTE:
-                MediaSessionLegacyHelper.getHelper(mApplicationContext)
+                MediaSessionLegacyHelper.getHelper(getContext())
                         .sendVolumeKeyEvent(event, false);
                 break;
         }
@@ -783,7 +803,7 @@
         IAudioService service = getService();
         try {
             service.adjustStreamVolume(streamType, direction, flags,
-                    mApplicationContext.getOpPackageName());
+                    getContext().getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in adjustStreamVolume", e);
         }
@@ -813,7 +833,7 @@
      * @see #isVolumeFixed()
      */
     public void adjustVolume(int direction, int flags) {
-        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
+        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
         helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
     }
 
@@ -842,7 +862,7 @@
      * @see #isVolumeFixed()
      */
     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
-        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
+        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
         helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
     }
 
@@ -850,7 +870,7 @@
     public void setMasterMute(boolean mute, int flags) {
         IAudioService service = getService();
         try {
-            service.setMasterMute(mute, flags, mApplicationContext.getOpPackageName());
+            service.setMasterMute(mute, flags, getContext().getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setMasterMute", e);
         }
@@ -997,7 +1017,7 @@
         }
         IAudioService service = getService();
         try {
-            service.setRingerModeExternal(ringerMode, mApplicationContext.getOpPackageName());
+            service.setRingerModeExternal(ringerMode, getContext().getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setRingerMode", e);
         }
@@ -1018,7 +1038,7 @@
     public void setStreamVolume(int streamType, int index, int flags) {
         IAudioService service = getService();
         try {
-            service.setStreamVolume(streamType, index, flags, mApplicationContext.getOpPackageName());
+            service.setStreamVolume(streamType, index, flags, getContext().getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setStreamVolume", e);
         }
@@ -1331,7 +1351,7 @@
      * @see #startBluetoothSco()
     */
     public boolean isBluetoothScoAvailableOffCall() {
-        return mApplicationContext.getResources().getBoolean(
+        return getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_bluetooth_sco_off_call);
     }
 
@@ -1384,7 +1404,7 @@
         IAudioService service = getService();
         try {
             service.startBluetoothSco(mICallBack,
-                    mApplicationContext.getApplicationInfo().targetSdkVersion);
+                    getContext().getApplicationInfo().targetSdkVersion);
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in startBluetoothSco", e);
         }
@@ -1532,7 +1552,7 @@
     public void setMicrophoneMute(boolean on){
         IAudioService service = getService();
         try {
-            service.setMicrophoneMute(on, mApplicationContext.getOpPackageName());
+            service.setMicrophoneMute(on, getContext().getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setMicrophoneMute", e);
         }
@@ -1963,7 +1983,7 @@
      * Settings has an in memory cache, so this is fast.
      */
     private boolean querySoundEffectsEnabled(int user) {
-        return Settings.System.getIntForUser(mApplicationContext.getContentResolver(),
+        return Settings.System.getIntForUser(getContext().getContentResolver(),
                 Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0;
     }
 
@@ -2375,7 +2395,7 @@
         try {
             status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack,
                     mAudioFocusDispatcher, getIdForAudioFocusListener(l),
-                    mApplicationContext.getOpPackageName() /* package name */, flags,
+                    getContext().getOpPackageName() /* package name */, flags,
                     ap != null ? ap.cb() : null);
         } catch (RemoteException e) {
             Log.e(TAG, "Can't call requestAudioFocus() on AudioService:", e);
@@ -2400,7 +2420,7 @@
                         .setInternalLegacyStreamType(streamType).build(),
                     durationHint, mICallBack, null,
                     AudioSystem.IN_VOICE_COMM_FOCUS_ID,
-                    mApplicationContext.getOpPackageName(),
+                    getContext().getOpPackageName(),
                     AUDIOFOCUS_FLAG_LOCK,
                     null /* policy token */);
         } catch (RemoteException e) {
@@ -2469,7 +2489,7 @@
         if (eventReceiver == null) {
             return;
         }
-        if (!eventReceiver.getPackageName().equals(mApplicationContext.getPackageName())) {
+        if (!eventReceiver.getPackageName().equals(getContext().getPackageName())) {
             Log.e(TAG, "registerMediaButtonEventReceiver() error: " +
                     "receiver and context package names don't match");
             return;
@@ -2478,7 +2498,7 @@
         Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
         //     the associated intent will be handled by the component being registered
         mediaButtonIntent.setComponent(eventReceiver);
-        PendingIntent pi = PendingIntent.getBroadcast(mApplicationContext,
+        PendingIntent pi = PendingIntent.getBroadcast(getContext(),
                 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
         registerMediaButtonIntent(pi, eventReceiver);
     }
@@ -2512,8 +2532,8 @@
             Log.e(TAG, "Cannot call registerMediaButtonIntent() with a null parameter");
             return;
         }
-        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
-        helper.addMediaButtonListener(pi, eventReceiver, mApplicationContext);
+        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
+        helper.addMediaButtonListener(pi, eventReceiver, getContext());
     }
 
     /**
@@ -2531,7 +2551,7 @@
         Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
         //     the associated intent will be handled by the component being registered
         mediaButtonIntent.setComponent(eventReceiver);
-        PendingIntent pi = PendingIntent.getBroadcast(mApplicationContext,
+        PendingIntent pi = PendingIntent.getBroadcast(getContext(),
                 0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
         unregisterMediaButtonIntent(pi);
     }
@@ -2554,7 +2574,7 @@
      * @hide
      */
     public void unregisterMediaButtonIntent(PendingIntent pi) {
-        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mApplicationContext);
+        MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(getContext());
         helper.removeMediaButtonListener(pi);
     }
 
@@ -2571,7 +2591,7 @@
         if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
             return;
         }
-        rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(mApplicationContext));
+        rcClient.registerWithSession(MediaSessionLegacyHelper.getHelper(getContext()));
     }
 
     /**
@@ -2586,7 +2606,7 @@
         if ((rcClient == null) || (rcClient.getRcMediaIntent() == null)) {
             return;
         }
-        rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(mApplicationContext));
+        rcClient.unregisterWithSession(MediaSessionLegacyHelper.getHelper(getContext()));
     }
 
     /**
@@ -3280,7 +3300,7 @@
      */
     public void setRingerModeInternal(int ringerMode) {
         try {
-            getService().setRingerModeInternal(ringerMode, mApplicationContext.getOpPackageName());
+            getService().setRingerModeInternal(ringerMode, getContext().getOpPackageName());
         } catch (RemoteException e) {
             Log.w(TAG, "Error calling setRingerModeInternal", e);
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 15d7367..756f5fc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3179,6 +3179,10 @@
                     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;
             }