Merge "Implement drawTextOnPath with Minikin"
diff --git a/api/current.txt b/api/current.txt
index 1906e7b..2912882 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8265,15 +8265,26 @@
   }
 
   public class LauncherApps {
+    method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
     method public void addOnAppsChangedListener(android.content.pm.LauncherApps.OnAppsChangedListener);
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
     method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
     method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
+    method public void removeOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
     method public void removeOnAppsChangedListener(android.content.pm.LauncherApps.OnAppsChangedListener);
     method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
     method public void startActivityForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
   }
 
+  public static abstract class LauncherApps.OnAppsChangedCallback {
+    ctor public LauncherApps.OnAppsChangedCallback();
+    method public abstract void onPackageAdded(java.lang.String, android.os.UserHandle);
+    method public abstract void onPackageChanged(java.lang.String, android.os.UserHandle);
+    method public abstract void onPackageRemoved(java.lang.String, android.os.UserHandle);
+    method public abstract void onPackagesAvailable(java.lang.String[], android.os.UserHandle, boolean);
+    method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
+  }
+
   public static abstract interface LauncherApps.OnAppsChangedListener {
     method public abstract void onPackageAdded(android.os.UserHandle, java.lang.String);
     method public abstract void onPackageChanged(android.os.UserHandle, java.lang.String);
@@ -21566,7 +21577,7 @@
     method public void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
     field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
     field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
-    field public static final java.lang.String DISALLOW_CONFIG_APPS = "no_config_apps";
+    field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps";
     field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
     field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
     field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 69fa408..6c10bb8 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -57,6 +57,65 @@
 
     private List<OnAppsChangedListener> mListeners
             = new ArrayList<OnAppsChangedListener>();
+    private List<OnAppsChangedCallback> mCallbacks
+            = new ArrayList<OnAppsChangedCallback>();
+
+    /**
+     * Callbacks for package changes to this and related managed profiles.
+     */
+    public static abstract class OnAppsChangedCallback {
+        /**
+         * Indicates that a package was removed from the specified profile.
+         *
+         * @param packageName The name of the package that was removed.
+         * @param user The UserHandle of the profile that generated the change.
+         */
+        abstract public void onPackageRemoved(String packageName, UserHandle user);
+
+        /**
+         * Indicates that a package was added to the specified profile.
+         *
+         * @param packageName The name of the package that was added.
+         * @param user The UserHandle of the profile that generated the change.
+         */
+        abstract public void onPackageAdded(String packageName, UserHandle user);
+
+        /**
+         * Indicates that a package was modified in the specified profile.
+         *
+         * @param packageName The name of the package that has changed.
+         * @param user The UserHandle of the profile that generated the change.
+         */
+        abstract public void onPackageChanged(String packageName, UserHandle user);
+
+        /**
+         * Indicates that one or more packages have become available. For
+         * example, this can happen when a removable storage card has
+         * reappeared.
+         *
+         * @param packageNames The names of the packages that have become
+         *            available.
+         * @param user The UserHandle of the profile that generated the change.
+         * @param replacing Indicates whether these packages are replacing
+         *            existing ones.
+         */
+        abstract public void onPackagesAvailable(String[] packageNames, UserHandle user,
+                boolean replacing);
+
+        /**
+         * Indicates that one or more packages have become unavailable. For
+         * example, this can happen when a removable storage card has been
+         * removed.
+         *
+         * @param packageNames The names of the packages that have become
+         *            unavailable.
+         * @param user The UserHandle of the profile that generated the change.
+         * @param replacing Indicates whether the packages are about to be
+         *            replaced with new versions.
+         */
+        abstract public void onPackagesUnavailable(String[] packageNames, UserHandle user,
+                boolean replacing);
+    }
 
     /**
      * Callbacks for package changes to this and related managed profiles.
@@ -270,7 +329,7 @@
         synchronized (this) {
             if (listener != null && !mListeners.contains(listener)) {
                 mListeners.add(listener);
-                if (mListeners.size() == 1) {
+                if (mListeners.size() == 1 && mCallbacks.size() == 0) {
                     try {
                         mService.addOnAppsChangedListener(mAppsChangedListener);
                     } catch (RemoteException re) {
@@ -289,7 +348,44 @@
     public void removeOnAppsChangedListener(OnAppsChangedListener listener) {
         synchronized (this) {
             mListeners.remove(listener);
-            if (mListeners.size() == 0) {
+            if (mListeners.size() == 0 && mCallbacks.size() == 0) {
+                try {
+                    mService.removeOnAppsChangedListener(mAppsChangedListener);
+                } catch (RemoteException re) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Adds a callback for changes to packages in current and managed profiles.
+     *
+     * @param callback The callback to add.
+     */
+    public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
+        synchronized (this) {
+            if (callback != null && !mCallbacks.contains(callback)) {
+                mCallbacks.add(callback);
+                if (mCallbacks.size() == 1 && mListeners.size() == 0) {
+                    try {
+                        mService.addOnAppsChangedListener(mAppsChangedListener);
+                    } catch (RemoteException re) {
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes a callback that was previously added.
+     *
+     * @param callback The callback to remove.
+     * @see #addOnAppsChangedListener(OnAppsChangedCallback)
+     */
+    public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
+        synchronized (this) {
+            mListeners.remove(callback);
+            if (mListeners.size() == 0 && mCallbacks.size() == 0) {
                 try {
                     mService.removeOnAppsChangedListener(mAppsChangedListener);
                 } catch (RemoteException re) {
@@ -309,6 +405,9 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackageRemoved(user, packageName);
                 }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackageRemoved(packageName, user);
+                }
             }
         }
 
@@ -321,6 +420,9 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackageChanged(user, packageName);
                 }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackageChanged(packageName, user);
+                }
             }
         }
 
@@ -333,6 +435,9 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackageAdded(user, packageName);
                 }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackageAdded(packageName, user);
+                }
             }
         }
 
@@ -346,6 +451,9 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackagesAvailable(user, packageNames, replacing);
                 }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackagesAvailable(packageNames, user, replacing);
+                }
             }
         }
 
@@ -359,7 +467,10 @@
                 for (OnAppsChangedListener listener : mListeners) {
                     listener.onPackagesUnavailable(user, packageNames, replacing);
                 }
-            }
+                for (OnAppsChangedCallback callback : mCallbacks) {
+                    callback.onPackagesUnavailable(packageNames, user, replacing);
+                }
+           }
         }
     };
 }
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 535bbe2..8142670 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -699,15 +699,15 @@
                 break;
             }
 
-            try {
-                if (enable) {
-                    return mPhoneService.enableApnType(apnType);
-                } else {
-                    return mPhoneService.disableApnType(apnType);
-                }
-            } catch (RemoteException e) {
-                if (retry == 0) getPhoneService(true);
-            }
+//            try {
+//                if (enable) {
+//                    return mPhoneService.enableApnType(apnType);
+//                } else {
+//                    return mPhoneService.disableApnType(apnType);
+//                }
+//            } catch (RemoteException e) {
+//                if (retry == 0) getPhoneService(true);
+//            }
         }
 
         loge("Could not " + (enable ? "enable" : "disable") + " APN type \"" + apnType + "\"");
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 468cfe0..757f38e 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -226,14 +226,14 @@
     public static final String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
 
     /**
-     * Key for user restrictions. Specifies if a user is disallowed from configuring
+     * Key for user restrictions. Specifies if a user is disallowed from controlling
      * applications in Settings. The default value is <code>false</code>.
      * <p>
      * Type: Boolean
      * @see #setUserRestrictions(Bundle)
      * @see #getUserRestrictions()
      */
-    public static final String DISALLOW_CONFIG_APPS = "no_config_apps";
+    public static final String DISALLOW_APPS_CONTROL = "no_control_apps";
 
     /**
      * Key for user restrictions. Specifies if a user is disallowed from mounting
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index b65af15..68e2146 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -804,20 +804,12 @@
 
     @Override
     public void drawPicture(Picture picture) {
-        if (picture.createdFromStream) {
-            return;
-        }
-
         picture.endRecording();
         // TODO: Implement rendering
     }
 
     @Override
     public void drawPicture(Picture picture, Rect dst) {
-        if (picture.createdFromStream) {
-            return;
-        }
-
         save();
         translate(dst.left, dst.top);
         if (picture.getWidth() > 0 && picture.getHeight() > 0) {
@@ -829,10 +821,6 @@
 
     @Override
     public void drawPicture(Picture picture, RectF dst) {
-        if (picture.createdFromStream) {
-            return;
-        }
-
         save();
         translate(dst.left, dst.top);
         if (picture.getWidth() > 0 && picture.getHeight() > 0) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 15dfed1..cb00062 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -89,7 +89,7 @@
 	android_util_Process.cpp \
 	android_util_StringBlock.cpp \
 	android_util_XmlBlock.cpp \
-	android/graphics/AndroidPicture.cpp \
+	android_graphics_Picture.cpp \
 	android/graphics/AutoDecodeCancel.cpp \
 	android/graphics/Bitmap.cpp \
 	android/graphics/BitmapFactory.cpp \
diff --git a/core/jni/android/graphics/AndroidPicture.cpp b/core/jni/android/graphics/AndroidPicture.cpp
deleted file mode 100644
index 5977ab2..0000000
--- a/core/jni/android/graphics/AndroidPicture.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "AndroidPicture.h"
-#include "SkCanvas.h"
-#include "SkStream.h"
-
-AndroidPicture::AndroidPicture(const AndroidPicture* src) {
-    if (NULL != src) {
-        mWidth = src->width();
-        mHeight = src->height();
-        if (NULL != src->mPicture.get()) {
-            mPicture.reset(SkRef(src->mPicture.get()));
-        } if (NULL != src->mRecorder.get()) {
-            mPicture.reset(src->makePartialCopy());
-        }
-    } else {
-        mWidth = 0;
-        mHeight = 0;
-    }
-}
-
-SkCanvas* AndroidPicture::beginRecording(int width, int height) {
-    mPicture.reset(NULL);
-    mRecorder.reset(new SkPictureRecorder);
-    mWidth = width;
-    mHeight = height;
-    return mRecorder->beginRecording(width, height, NULL, 0);
-}
-
-void AndroidPicture::endRecording() {
-    if (NULL != mRecorder.get()) {
-        mPicture.reset(mRecorder->endRecording());
-        mRecorder.reset(NULL);
-    }
-}
-
-int AndroidPicture::width() const {
-    if (NULL != mPicture.get()) {
-        SkASSERT(mPicture->width() == mWidth);
-        SkASSERT(mPicture->height() == mHeight);
-    }
-
-    return mWidth;
-}
-
-int AndroidPicture::height() const {
-    if (NULL != mPicture.get()) {
-        SkASSERT(mPicture->width() == mWidth);
-        SkASSERT(mPicture->height() == mHeight);
-    }
-
-    return mHeight;
-}
-
-AndroidPicture* AndroidPicture::CreateFromStream(SkStream* stream) {
-    AndroidPicture* newPict = new AndroidPicture;
-
-    newPict->mPicture.reset(SkPicture::CreateFromStream(stream));
-    if (NULL != newPict->mPicture.get()) {
-        newPict->mWidth = newPict->mPicture->width();
-        newPict->mHeight = newPict->mPicture->height();
-    }
-
-    return newPict;
-}
-
-void AndroidPicture::serialize(SkWStream* stream) const {
-    if (NULL != mRecorder.get()) {
-        SkAutoTDelete<SkPicture> tempPict(this->makePartialCopy());
-        tempPict->serialize(stream);
-    } else if (NULL != mPicture.get()) {
-        mPicture->serialize(stream);
-    } else {
-        SkPicture empty;
-        empty.serialize(stream);
-    }
-}
-
-void AndroidPicture::draw(SkCanvas* canvas) {
-    if (NULL != mRecorder.get()) {
-        this->endRecording();
-        SkASSERT(NULL != mPicture.get());
-    }
-    if (NULL != mPicture.get()) {
-        // TODO: remove this const_cast once pictures are immutable
-        const_cast<SkPicture*>(mPicture.get())->draw(canvas);
-    }
-}
-
-SkPicture* AndroidPicture::makePartialCopy() const {
-    SkASSERT(NULL != mRecorder.get());
-
-    SkPictureRecorder reRecorder;
-
-    SkCanvas* canvas = reRecorder.beginRecording(mWidth, mHeight, NULL, 0);
-    mRecorder->partialReplay(canvas);
-    return reRecorder.endRecording();
-}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index a4337cc..2bd7a28 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -3,7 +3,6 @@
 #include "jni.h"
 #include "JNIHelp.h"
 #include "GraphicsJNI.h"
-#include "AndroidPicture.h"
 
 #include "SkCanvas.h"
 #include "SkDevice.h"
@@ -346,17 +345,6 @@
     return p;
 }
 
-AndroidPicture* GraphicsJNI::getNativePicture(JNIEnv* env, jobject picture)
-{
-    SkASSERT(env);
-    SkASSERT(picture);
-    SkASSERT(env->IsInstanceOf(picture, gPicture_class));
-    jlong pictureHandle = env->GetLongField(picture, gPicture_nativeInstanceID);
-    AndroidPicture* p = reinterpret_cast<AndroidPicture*>(pictureHandle);
-    SkASSERT(p);
-    return p;
-}
-
 SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region)
 {
     SkASSERT(env);
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 2e2f920..ad174f7 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -14,7 +14,6 @@
 class SkBitmapRegionDecoder;
 class SkCanvas;
 class SkPaint;
-class AndroidPicture;
 
 class GraphicsJNI {
 public:
@@ -50,7 +49,6 @@
     static SkPaint*  getNativePaint(JNIEnv*, jobject paint);
     static android::TypefaceImpl* getNativeTypeface(JNIEnv*, jobject paint);
     static SkBitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
-    static AndroidPicture* getNativePicture(JNIEnv*, jobject picture);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
 
     // Given the 'native' long held by the Rasterizer.java object, return a
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index 0683f73..4a62dc2 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,123 +14,102 @@
  * limitations under the License.
  */
 
-#include "jni.h"
-#include "GraphicsJNI.h"
-#include <android_runtime/AndroidRuntime.h>
-#include "AndroidPicture.h"
+#include "Picture.h"
 
 #include "SkCanvas.h"
 #include "SkStream.h"
-#include "SkTemplates.h"
-#include "CreateJavaOutputStreamAdaptor.h"
 
-namespace android {
+using namespace android;
 
-class SkPictureGlue {
-public:
-    static jlong newPicture(JNIEnv* env, jobject, jlong srcHandle) {
-        const AndroidPicture* src = reinterpret_cast<AndroidPicture*>(srcHandle);
-        return reinterpret_cast<jlong>(new AndroidPicture(src));
-    }
-
-    static jlong deserialize(JNIEnv* env, jobject, jobject jstream,
-                             jbyteArray jstorage) {
-        AndroidPicture* picture = NULL;
-        SkStream* strm = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
-        if (strm) {
-            picture = AndroidPicture::CreateFromStream(strm);
-            delete strm;
+Picture::Picture(const Picture* src) {
+    if (NULL != src) {
+        mWidth = src->width();
+        mHeight = src->height();
+        if (NULL != src->mPicture.get()) {
+            mPicture.reset(SkRef(src->mPicture.get()));
+        } if (NULL != src->mRecorder.get()) {
+            mPicture.reset(src->makePartialCopy());
         }
-        return reinterpret_cast<jlong>(picture);
+    } else {
+        mWidth = 0;
+        mHeight = 0;
     }
-
-    static void killPicture(JNIEnv* env, jobject, jlong pictureHandle) {
-        AndroidPicture* picture = reinterpret_cast<AndroidPicture*>(pictureHandle);
-        SkASSERT(picture);
-        delete picture;
-    }
-
-    static void draw(JNIEnv* env, jobject, jlong canvasHandle,
-                            jlong pictureHandle) {
-        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
-        AndroidPicture* picture = reinterpret_cast<AndroidPicture*>(pictureHandle);
-        SkASSERT(canvas);
-        SkASSERT(picture);
-        picture->draw(canvas);
-    }
-
-    static jboolean serialize(JNIEnv* env, jobject, jlong pictureHandle,
-                              jobject jstream, jbyteArray jstorage) {
-        AndroidPicture* picture = reinterpret_cast<AndroidPicture*>(pictureHandle);
-        SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
-
-        if (NULL != strm) {
-            picture->serialize(strm);
-            delete strm;
-            return JNI_TRUE;
-        }
-        return JNI_FALSE;
-    }
-
-    static jint getWidth(JNIEnv* env, jobject jpic) {
-        NPE_CHECK_RETURN_ZERO(env, jpic);
-        AndroidPicture* pict = GraphicsJNI::getNativePicture(env, jpic);
-        int width = pict->width();
-        return static_cast<jint>(width);
-    }
-
-    static jint getHeight(JNIEnv* env, jobject jpic) {
-        NPE_CHECK_RETURN_ZERO(env, jpic);
-        AndroidPicture* pict = GraphicsJNI::getNativePicture(env, jpic);
-        int height = pict->height();
-        return static_cast<jint>(height);
-    }
-
-    static jlong beginRecording(JNIEnv* env, jobject, jlong pictHandle,
-                                jint w, jint h) {
-        AndroidPicture* pict = reinterpret_cast<AndroidPicture*>(pictHandle);
-        // beginRecording does not ref its return value, it just returns it.
-        SkCanvas* canvas = pict->beginRecording(w, h);
-        // the java side will wrap this guy in a Canvas.java, which will call
-        // unref in its finalizer, so we have to ref it here, so that both that
-        // Canvas.java and our picture can both be owners
-        canvas->ref();
-        return reinterpret_cast<jlong>(canvas);
-    }
-
-    static void endRecording(JNIEnv* env, jobject, jlong pictHandle) {
-        AndroidPicture* pict = reinterpret_cast<AndroidPicture*>(pictHandle);
-        pict->endRecording();
-    }
-};
-
-static JNINativeMethod gPictureMethods[] = {
-    {"getWidth", "()I", (void*) SkPictureGlue::getWidth},
-    {"getHeight", "()I", (void*) SkPictureGlue::getHeight},
-    {"nativeConstructor", "(J)J", (void*) SkPictureGlue::newPicture},
-    {"nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", (void*)SkPictureGlue::deserialize},
-    {"nativeBeginRecording", "(JII)J", (void*) SkPictureGlue::beginRecording},
-    {"nativeEndRecording", "(J)V", (void*) SkPictureGlue::endRecording},
-    {"nativeDraw", "(JJ)V", (void*) SkPictureGlue::draw},
-    {"nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", (void*)SkPictureGlue::serialize},
-    {"nativeDestructor","(J)V", (void*) SkPictureGlue::killPicture}
-};
-
-#include <android_runtime/AndroidRuntime.h>
-
-#define REG(env, name, array) \
-    result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
-    SK_ARRAY_COUNT(array));  \
-    if (result < 0) return result
-
-int register_android_graphics_Picture(JNIEnv* env) {
-    int result;
-
-    REG(env, "android/graphics/Picture", gPictureMethods);
-
-    return result;
 }
 
+SkCanvas* Picture::beginRecording(int width, int height) {
+    mPicture.reset(NULL);
+    mRecorder.reset(new SkPictureRecorder);
+    mWidth = width;
+    mHeight = height;
+    return mRecorder->beginRecording(width, height, NULL, 0);
 }
 
+void Picture::endRecording() {
+    if (NULL != mRecorder.get()) {
+        mPicture.reset(mRecorder->endRecording());
+        mRecorder.reset(NULL);
+    }
+}
 
+int Picture::width() const {
+    if (NULL != mPicture.get()) {
+        SkASSERT(mPicture->width() == mWidth);
+        SkASSERT(mPicture->height() == mHeight);
+    }
+
+    return mWidth;
+}
+
+int Picture::height() const {
+    if (NULL != mPicture.get()) {
+        SkASSERT(mPicture->width() == mWidth);
+        SkASSERT(mPicture->height() == mHeight);
+    }
+
+    return mHeight;
+}
+
+Picture* Picture::CreateFromStream(SkStream* stream) {
+    Picture* newPict = new Picture;
+
+    newPict->mPicture.reset(SkPicture::CreateFromStream(stream));
+    if (NULL != newPict->mPicture.get()) {
+        newPict->mWidth = newPict->mPicture->width();
+        newPict->mHeight = newPict->mPicture->height();
+    }
+
+    return newPict;
+}
+
+void Picture::serialize(SkWStream* stream) const {
+    if (NULL != mRecorder.get()) {
+        SkAutoTDelete<SkPicture> tempPict(this->makePartialCopy());
+        tempPict->serialize(stream);
+    } else if (NULL != mPicture.get()) {
+        mPicture->serialize(stream);
+    } else {
+        SkPicture empty;
+        empty.serialize(stream);
+    }
+}
+
+void Picture::draw(SkCanvas* canvas) {
+    if (NULL != mRecorder.get()) {
+        this->endRecording();
+        SkASSERT(NULL != mPicture.get());
+    }
+    if (NULL != mPicture.get()) {
+        // TODO: remove this const_cast once pictures are immutable
+        const_cast<SkPicture*>(mPicture.get())->draw(canvas);
+    }
+}
+
+SkPicture* Picture::makePartialCopy() const {
+    SkASSERT(NULL != mRecorder.get());
+
+    SkPictureRecorder reRecorder;
+
+    SkCanvas* canvas = reRecorder.beginRecording(mWidth, mHeight, NULL, 0);
+    mRecorder->partialReplay(canvas);
+    return reRecorder.endRecording();
+}
diff --git a/core/jni/android/graphics/AndroidPicture.h b/core/jni/android/graphics/Picture.h
similarity index 85%
rename from core/jni/android/graphics/AndroidPicture.h
rename to core/jni/android/graphics/Picture.h
index f434941..abb0403 100644
--- a/core/jni/android/graphics/AndroidPicture.h
+++ b/core/jni/android/graphics/Picture.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PICTURE_H
-#define ANDROID_PICTURE_H
+#ifndef ANDROID_GRAPHICS_PICTURE_H
+#define ANDROID_GRAPHICS_PICTURE_H
 
 #include "SkPicture.h"
 #include "SkPictureRecorder.h"
@@ -28,13 +28,15 @@
 class SkStream;
 class SkWStream;
 
+namespace android {
+
 // Skia's SkPicture class has been split into an SkPictureRecorder
 // and an SkPicture. AndroidPicture recreates the functionality
 // of the old SkPicture interface by flip-flopping between the two
 // new classes.
-class AndroidPicture {
+class Picture {
 public:
-    explicit AndroidPicture(const AndroidPicture* src = NULL);
+    explicit Picture(const Picture* src = NULL);
 
     SkCanvas* beginRecording(int width, int height);
 
@@ -44,7 +46,7 @@
 
     int height() const;
 
-    static AndroidPicture* CreateFromStream(SkStream* stream);
+    static Picture* CreateFromStream(SkStream* stream);
 
     void serialize(SkWStream* stream) const;
 
@@ -60,4 +62,6 @@
     // resulting picture will have balanced saves and restores.
     SkPicture* makePartialCopy() const;
 };
-#endif // ANDROID_PICTURE_H
+
+}; // namespace android
+#endif // ANDROID_GRAPHICS_PICTURE_H
diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp
new file mode 100644
index 0000000..f827907
--- /dev/null
+++ b/core/jni/android_graphics_Picture.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "Picture.h"
+
+#include "SkCanvas.h"
+#include "SkStream.h"
+#include "SkTemplates.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+
+namespace android {
+
+static jlong android_graphics_Picture_newPicture(JNIEnv* env, jobject, jlong srcHandle) {
+    const Picture* src = reinterpret_cast<Picture*>(srcHandle);
+    return reinterpret_cast<jlong>(new Picture(src));
+}
+
+static jlong android_graphics_Picture_deserialize(JNIEnv* env, jobject, jobject jstream,
+                                                  jbyteArray jstorage) {
+    Picture* picture = NULL;
+    SkStream* strm = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
+    if (strm) {
+        picture = Picture::CreateFromStream(strm);
+        delete strm;
+    }
+    return reinterpret_cast<jlong>(picture);
+}
+
+static void android_graphics_Picture_killPicture(JNIEnv* env, jobject, jlong pictureHandle) {
+    Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+    SkASSERT(picture);
+    delete picture;
+}
+
+static void android_graphics_Picture_draw(JNIEnv* env, jobject, jlong canvasHandle,
+                                          jlong pictureHandle) {
+    SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
+    Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+    SkASSERT(canvas);
+    SkASSERT(picture);
+    picture->draw(canvas);
+}
+
+static jboolean android_graphics_Picture_serialize(JNIEnv* env, jobject, jlong pictureHandle,
+                                                   jobject jstream, jbyteArray jstorage) {
+    Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+    SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
+
+    if (NULL != strm) {
+        picture->serialize(strm);
+        delete strm;
+        return JNI_TRUE;
+    }
+    return JNI_FALSE;
+}
+
+static jint android_graphics_Picture_getWidth(JNIEnv* env, jobject, jlong pictureHandle) {
+    Picture* pict = reinterpret_cast<Picture*>(pictureHandle);
+    return static_cast<jint>(pict->width());
+}
+
+static jint android_graphics_Picture_getHeight(JNIEnv* env, jobject, jlong pictureHandle) {
+    Picture* pict = reinterpret_cast<Picture*>(pictureHandle);
+    return static_cast<jint>(pict->height());
+}
+
+static jlong android_graphics_Picture_beginRecording(JNIEnv* env, jobject, jlong pictHandle,
+                                                     jint w, jint h) {
+    Picture* pict = reinterpret_cast<Picture*>(pictHandle);
+    // beginRecording does not ref its return value, it just returns it.
+    SkCanvas* canvas = pict->beginRecording(w, h);
+    // the java side will wrap this guy in a Canvas.java, which will call
+    // unref in its finalizer, so we have to ref it here, so that both that
+    // Canvas.java and our picture can both be owners
+    canvas->ref();
+    return reinterpret_cast<jlong>(canvas);
+}
+
+static void android_graphics_Picture_endRecording(JNIEnv* env, jobject, jlong pictHandle) {
+    Picture* pict = reinterpret_cast<Picture*>(pictHandle);
+    pict->endRecording();
+}
+
+static JNINativeMethod gMethods[] = {
+    {"nativeGetWidth", "(J)I", (void*) android_graphics_Picture_getWidth},
+    {"nativeGetHeight", "(J)I", (void*) android_graphics_Picture_getHeight},
+    {"nativeConstructor", "(J)J", (void*) android_graphics_Picture_newPicture},
+    {"nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", (void*)android_graphics_Picture_deserialize},
+    {"nativeBeginRecording", "(JII)J", (void*) android_graphics_Picture_beginRecording},
+    {"nativeEndRecording", "(J)V", (void*) android_graphics_Picture_endRecording},
+    {"nativeDraw", "(JJ)V", (void*) android_graphics_Picture_draw},
+    {"nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", (void*)android_graphics_Picture_serialize},
+    {"nativeDestructor","(J)V", (void*) android_graphics_Picture_killPicture}
+};
+
+int register_android_graphics_Picture(JNIEnv* env) {
+    return AndroidRuntime::registerNativeMethods(env, "android/graphics/Picture", gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index a021165..5aa7c6a 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -31,18 +31,13 @@
     private Canvas mRecordingCanvas;
     private final long mNativePicture;
 
-    /**
-     * @hide
-     */
-    public final boolean createdFromStream;
-
     private static final int WORKING_STREAM_STORAGE = 16 * 1024;
 
     /**
      * Creates an empty picture that is ready to record.
      */
     public Picture() {
-        this(nativeConstructor(0), false);
+        this(nativeConstructor(0));
     }
 
     /**
@@ -51,7 +46,23 @@
      * changes will not be reflected in this picture.
      */
     public Picture(Picture src) {
-        this(nativeConstructor(src != null ? src.mNativePicture : 0), false);
+        this(nativeConstructor(src != null ? src.mNativePicture : 0));
+    }
+
+    private Picture(long nativePicture) {
+        if (nativePicture == 0) {
+            throw new RuntimeException();
+        }
+        mNativePicture = nativePicture;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            nativeDestructor(mNativePicture);
+        } finally {
+            super.finalize();
+        }
     }
 
     /**
@@ -85,13 +96,17 @@
      * Get the width of the picture as passed to beginRecording. This
      * does not reflect (per se) the content of the picture.
      */
-    public native int getWidth();
+    public int getWidth() {
+      return nativeGetWidth(mNativePicture);
+    }
 
     /**
      * Get the height of the picture as passed to beginRecording. This
      * does not reflect (per se) the content of the picture.
      */
-    public native int getHeight();
+    public int getHeight() {
+      return nativeGetHeight(mNativePicture);
+    }
 
     /**
      * Draw this picture on the canvas.
@@ -130,7 +145,7 @@
      */
     @Deprecated
     public static Picture createFromStream(InputStream stream) {
-        return new Picture(nativeCreateFromStream(stream, new byte[WORKING_STREAM_STORAGE]), true);
+        return new Picture(nativeCreateFromStream(stream, new byte[WORKING_STREAM_STORAGE]));
     }
 
     /**
@@ -159,32 +174,12 @@
         }
     }
 
-    protected void finalize() throws Throwable {
-        try {
-            nativeDestructor(mNativePicture);
-        } finally {
-            super.finalize();
-        }
-    }
-
-    final long ni() {
-        return mNativePicture;
-    }
-
-    private Picture(long nativePicture, boolean fromStream) {
-        if (nativePicture == 0) {
-            throw new RuntimeException();
-        }
-        mNativePicture = nativePicture;
-        createdFromStream = fromStream;
-    }
-
     // return empty picture if src is 0, or a copy of the native src
     private static native long nativeConstructor(long nativeSrcOr0);
-    private static native long nativeCreateFromStream(InputStream stream,
-                                                byte[] storage);
-    private static native long nativeBeginRecording(long nativeCanvas,
-                                                    int w, int h);
+    private static native long nativeCreateFromStream(InputStream stream, byte[] storage);
+    private static native int nativeGetWidth(long nativePicture);
+    private static native int nativeGetHeight(long nativePicture);
+    private static native long nativeBeginRecording(long nativeCanvas, int w, int h);
     private static native void nativeEndRecording(long nativeCanvas);
     private static native void nativeDraw(long nativeCanvas, long nativePicture);
     private static native boolean nativeWriteToStream(long nativePicture,
@@ -201,18 +196,15 @@
 
         @Override
         public void setBitmap(Bitmap bitmap) {
-            throw new RuntimeException(
-                                "Cannot call setBitmap on a picture canvas");
+            throw new RuntimeException("Cannot call setBitmap on a picture canvas");
         }
 
         @Override
         public void drawPicture(Picture picture) {
             if (mPicture == picture) {
-                throw new RuntimeException(
-                            "Cannot draw a picture into its recording canvas");
+                throw new RuntimeException("Cannot draw a picture into its recording canvas");
             }
             super.drawPicture(picture);
         }
     }
 }
-
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index be940df..0a394d5 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -928,7 +928,7 @@
             mTargetDensity = state.mTargetDensity;
         }
 
-        updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
+        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
         computeBitmapSize();
     }
 }
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index f70110c..bdd1195 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -583,7 +583,8 @@
     }
 
     /**
-     * Get the altitude if available, in meters above sea level.
+     * Get the altitude if available, in meters above the WGS 84 reference
+     * ellipsoid.
      *
      * <p>If this location does not have an altitude then 0.0 is returned.
      */
@@ -592,7 +593,7 @@
     }
 
     /**
-     * Set the altitude, in meters above sea level.
+     * Set the altitude, in meters above the WGS 84 reference ellipsoid.
      *
      * <p>Following this call {@link #hasAltitude} will return true.
      */
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 4b4be1b..e05aef0 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -152,6 +152,8 @@
         switch (audioFormat) {
         case ENCODING_PCM_8BIT:
             return 1;
+        case ENCODING_PCM_FLOAT:
+            return 4;
         case ENCODING_PCM_16BIT:
         case ENCODING_DEFAULT:
             return 2;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index e25714a..66175d0 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1826,11 +1826,7 @@
             }
             SubtitleTrack track = mInbandSubtitleTracks[index];
             if (track != null) {
-                long runID = data.getStartTimeUs() + 1;
-                track.onData(data.getData(), true /* eos */, runID);
-                track.setRunDiscardTimeMs(
-                        runID,
-                        (data.getStartTimeUs() + data.getDurationUs()) / 1000);
+                track.onData(data);
             }
         }
     };
diff --git a/media/java/android/media/SubtitleTrack.java b/media/java/android/media/SubtitleTrack.java
index b0e182d..9fedf63 100644
--- a/media/java/android/media/SubtitleTrack.java
+++ b/media/java/android/media/SubtitleTrack.java
@@ -75,6 +75,14 @@
 
     private long mNextScheduledTimeMs = -1;
 
+    protected void onData(SubtitleData data) {
+        long runID = data.getStartTimeUs() + 1;
+        onData(data.getData(), true /* eos */, runID);
+        setRunDiscardTimeMs(
+                runID,
+                (data.getStartTimeUs() + data.getDurationUs()) / 1000);
+    }
+
     /**
      * Called when there is input data for the subtitle track.  The
      * complete subtitle for a track can include multiple whole units
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 3f0405d..bbe650d 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -848,7 +848,7 @@
      *
      * @hide
      */
-    public static final class WatchedPrograms implements BaseColumns {
+    public static final class WatchedPrograms implements BaseTvColumns {
 
         /** The content:// style URI for this table. */
         public static final Uri CONTENT_URI =
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 9d92421..1bd837b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -89,7 +89,7 @@
 
         @Override
         public String toString() {
-            return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid +
+            return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid + " subId=" + subId +
                     " events=" + Integer.toHexString(events) + "}";
         }
     }
@@ -208,11 +208,13 @@
             String action = intent.getAction();
             Slog.d(TAG, "mBroadcastReceiver: action=" + action);
             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
-                       intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+                int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                if (DBG) Slog.d(TAG, "onReceive: userHandle=" + userHandle);
+                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED, userHandle, 0));
             } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_SUBSCRIPTION_CHANGED)) {
                 mDefaultSubId = intent.getLongExtra(PhoneConstants.SUBSCRIPTION_KEY,
                         SubscriptionManager.getDefaultSubId());
+                if (DBG) Slog.d(TAG, "onReceive: mDefaultSubId=" + mDefaultSubId);
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_DEFAULT_SUB, 0, 0));
             }
         }
@@ -340,18 +342,19 @@
                     // the received subId value update the isLegacyApp field
                     if ((r.subId <= 0) || (r.subId == SubscriptionManager.INVALID_SUB_ID)) {
                         r.subId = mDefaultSubId;
-                        r.isLegacyApp = true; // FIXME: is this needed ??
+                        r.isLegacyApp = true; // r.subId is to be update when default changes.
                     }
                     if (r.subId == SubscriptionManager.DEFAULT_SUB_ID) {
                         r.subId = mDefaultSubId;
+                        r.isLegacyApp = true; // r.subId is to be update when default changes.
                         if (DBG) Slog.i(TAG, "listen: DEFAULT_SUB_ID");
                     }
                     mRecords.add(r);
-                    if (DBG) Slog.i(TAG, "listen: add new record=" + r);
+                    if (DBG) Slog.i(TAG, "listen: add new record");
                 }
                 int phoneId = SubscriptionManager.getPhoneId(subId);
-                int send = events & (events ^ r.events);
                 r.events = events;
+                if (DBG) Slog.i(TAG, "listen: set events record=" + r);
                 if (notifyNow && validatePhoneId(phoneId)) {
                     if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
                         try {
@@ -1063,6 +1066,7 @@
             pw.println("  mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
             pw.println("  mDataConnectionNetworkCapabilities=" +
                     mDataConnectionNetworkCapabilities);
+            pw.println("  mDefaultSubId=" + mDefaultSubId);
             pw.println("  mCellLocation=" + mCellLocation);
             pw.println("  mCellInfo=" + mCellInfo);
             pw.println("  mDcRtInfo=" + mDcRtInfo);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index b941657..1839259 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -744,7 +744,7 @@
                 writeBoolean(serializer, restrictions, UserManager.ENSURE_VERIFY_APPS);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
-                writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_APPS);
+                writeBoolean(serializer, restrictions, UserManager.DISALLOW_APPS_CONTROL);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
@@ -896,7 +896,7 @@
                         readBoolean(parser, restrictions, UserManager.ENSURE_VERIFY_APPS);
                         readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
                         readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
-                        readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_APPS);
+                        readBoolean(parser, restrictions, UserManager.DISALLOW_APPS_CONTROL);
                         readBoolean(parser, restrictions,
                                 UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
                         readBoolean(parser, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 10a67c4..cbbcc58 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -19,12 +19,15 @@
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.OperationApplicationException;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -66,11 +69,12 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /** This class provides a system service that manages television inputs. */
 public final class TvInputManagerService extends SystemService {
@@ -123,6 +127,44 @@
                     buildTvInputListLocked(mCurrentUserId);
                 }
             }
+
+            @Override
+            public void onPackageRemoved(String packageName, int uid) {
+                synchronized (mLock) {
+                    UserState userState = getUserStateLocked(mCurrentUserId);
+                    if (!userState.packageList.contains(packageName)) {
+                        // Not a TV input package.
+                        return;
+                    }
+                }
+
+                ArrayList<ContentProviderOperation> operations =
+                        new ArrayList<ContentProviderOperation>();
+
+                String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?";
+                String[] selectionArgs = { packageName };
+
+                operations.add(ContentProviderOperation.newDelete(TvContract.Channels.CONTENT_URI)
+                        .withSelection(selection, selectionArgs).build());
+                operations.add(ContentProviderOperation.newDelete(TvContract.Programs.CONTENT_URI)
+                        .withSelection(selection, selectionArgs).build());
+                operations.add(ContentProviderOperation
+                        .newDelete(TvContract.WatchedPrograms.CONTENT_URI)
+                        .withSelection(selection, selectionArgs).build());
+
+                ContentProviderResult[] results = null;
+                try {
+                    results = mContentResolver.applyBatch(TvContract.AUTHORITY, operations);
+                } catch (RemoteException | OperationApplicationException e) {
+                    Slog.e(TAG, "error in applyBatch" + e);
+                }
+
+                if (DEBUG) {
+                    Slog.d(TAG, "onPackageRemoved(packageName=" + packageName + ", uid=" + uid
+                            + ")");
+                    Slog.d(TAG, "results=" + results);
+                }
+            }
         };
         monitor.register(mContext, null, UserHandle.ALL, true);
 
@@ -145,6 +187,7 @@
     private void buildTvInputListLocked(int userId) {
         UserState userState = getUserStateLocked(userId);
         userState.inputMap.clear();
+        userState.packageList.clear();
 
         if (DEBUG) Slog.d(TAG, "buildTvInputList");
         PackageManager pm = mContext.getPackageManager();
@@ -162,6 +205,7 @@
                 TvInputInfo info = TvInputInfo.createTvInputInfo(mContext, ri);
                 if (DEBUG) Slog.d(TAG, "add " + info.getId());
                 userState.inputMap.put(info.getId(), info);
+                userState.packageList.add(si.packageName);
             } catch (IOException | XmlPullParserException e) {
                 Slog.e(TAG, "Can't load TV input " + si.name, e);
             }
@@ -348,7 +392,7 @@
                     if (session == null) {
                         removeSessionStateLocked(sessionToken, userId);
                         sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInputId,
-                                null, null, sessionState.mSeq, userId);
+                                null, null, sessionState.mSeq);
                     } else {
                         try {
                             session.asBinder().linkToDeath(sessionState, 0);
@@ -364,7 +408,7 @@
                         clientState.mSessionTokens.add(sessionState.mSessionToken);
 
                         sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInputId,
-                                sessionToken, channels[0], sessionState.mSeq, userId);
+                                sessionToken, channels[0], sessionState.mSeq);
                     }
                     channels[0].dispose();
                 }
@@ -449,13 +493,13 @@
             Slog.e(TAG, "error in createSession", e);
             removeSessionStateLocked(sessionToken, userId);
             sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInputId, null, null,
-                    sessionState.mSeq, userId);
+                    sessionState.mSeq);
         }
         channels[1].dispose();
     }
 
     private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId,
-            IBinder sessionToken, InputChannel channel, int seq, int userId) {
+            IBinder sessionToken, InputChannel channel, int seq) {
         try {
             client.onSessionCreated(inputId, sessionToken, channel, seq);
         } catch (RemoteException exception) {
@@ -672,7 +716,7 @@
                     }
                     // Send a null token immediately while reconnecting.
                     if (serviceState.mReconnecting == true) {
-                        sendSessionTokenToClientLocked(client, inputId, null, null, seq, userId);
+                        sendSessionTokenToClientLocked(client, inputId, null, null, seq);
                         return;
                     }
 
@@ -784,7 +828,10 @@
                         }
 
                         // Create a log entry and fill it later.
+                        String packageName = userState.inputMap.get(sessionState.mInputId)
+                                .getServiceInfo().packageName;
                         ContentValues values = new ContentValues();
+                        values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName);
                         values.put(TvContract.WatchedPrograms.COLUMN_WATCH_START_TIME_UTC_MILLIS,
                                 currentTime);
                         values.put(TvContract.WatchedPrograms.COLUMN_WATCH_END_TIME_UTC_MILLIS, 0);
@@ -931,6 +978,9 @@
         // A mapping from the TV input id to its TvInputInfo.
         private final Map<String, TvInputInfo> inputMap = new HashMap<String,TvInputInfo>();
 
+        // A list of all TV input packages.
+        private final Set<String> packageList = new HashSet<String>();
+
         // A mapping from the token of a client to its state.
         private final Map<IBinder, ClientState> clientStateMap =
                 new HashMap<IBinder, ClientState>();
@@ -1095,8 +1145,7 @@
                         if (sessionState.mSession == null) {
                             removeSessionStateLocked(sessionToken, sessionState.mUserId);
                             sendSessionTokenToClientLocked(sessionState.mClient,
-                                    sessionState.mInputId, null, null, sessionState.mSeq,
-                                    sessionState.mUserId);
+                                    sessionState.mInputId, null, null, sessionState.mSeq);
                         }
                     }
 
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index 670def7..ced8e2f 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -105,4 +105,11 @@
         return 0;
     }
 
+    public String toString() {
+        return "{mSubId=" + mSubId + ", mIccId=" + mIccId + " mSlotId=" + mSlotId
+                + " mDisplayName=" + mDisplayName + " mNameSource=" + mNameSource
+                + " mColor=" + mColor + " mNumber=" + mNumber
+                + " mDispalyNumberFormat=" + mDispalyNumberFormat + " mDataRoaming=" + mDataRoaming
+                + " mSimIconRes=" + mSimIconRes + "}";
+    }
 }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 859a890..79e9fd5 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -697,12 +697,16 @@
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
         long [] subId = SubscriptionManager.getSubId(phoneId);
         if ((subId != null) && (subId.length >= 1)) {
-            if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
-            intent.putExtra(PhoneConstants.SLOT_KEY, phoneId); //FIXME: RENAME TO PHONE_ID_KEY ??
-            intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId[0]);
+            putPhoneIdAndSubIdExtra(intent, phoneId, subId[0]);
         } else {
             logd("putPhoneIdAndSubIdExtra: no valid subs");
         }
     }
+
+    public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, long subId) {
+        if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
+        intent.putExtra(PhoneConstants.SLOT_KEY, phoneId); //FIXME: RENAME TO PHONE_ID_KEY ??
+        intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+    }
 }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3fde36e..124a8ec 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3035,28 +3035,6 @@
 
     /** @hide */
     @SystemApi
-    public int enableApnType(String type) {
-        try {
-            return getITelephony().enableApnType(type);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#enableApnType", e);
-        }
-        return PhoneConstants.APN_REQUEST_FAILED;
-    }
-
-    /** @hide */
-    @SystemApi
-    public int disableApnType(String type) {
-        try {
-            return getITelephony().disableApnType(type);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#disableApnType", e);
-        }
-        return PhoneConstants.APN_REQUEST_FAILED;
-    }
-
-    /** @hide */
-    @SystemApi
     public boolean enableDataConnectivity() {
         try {
             return getITelephony().enableDataConnectivity();
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 407da87..beee616 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -310,27 +310,6 @@
      */
     void disableLocationUpdatesUsingSubId(long subId);
 
-
-    /**
-     * Enable a specific APN type.
-     */
-    int enableApnType(String type);
-
-    /**
-     * Disable a specific APN type.
-     */
-    int disableApnType(String type);
-
-    /**
-     * Enable a specific APN type with subscription.
-     */
-    int enableApnTypeUsingSub(long subId, String type);
-
-    /**
-     * Disable a specific APN type with subscription.
-     */
-    int disableApnTypeUsingSub(long subId, String type);
-
     /**
      * Allow mobile data connections.
      */